pure-admin-rails 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +131 -0
  4. data/app/assets/images/menu-fade-left.png +0 -0
  5. data/app/assets/images/menu-fade-right.png +0 -0
  6. data/app/assets/images/pending.gif +0 -0
  7. data/app/assets/javascripts/pure_admin.js +6 -0
  8. data/app/assets/javascripts/pure_admin/dropdown.js +178 -0
  9. data/app/assets/javascripts/pure_admin/flash_messages.js +13 -0
  10. data/app/assets/javascripts/pure_admin/inputs.js +24 -0
  11. data/app/assets/javascripts/pure_admin/inputs/select.js +21 -0
  12. data/app/assets/javascripts/pure_admin/main_header.js +21 -0
  13. data/app/assets/javascripts/pure_admin/main_menu.js +108 -0
  14. data/app/assets/javascripts/pure_admin/modals.js +228 -0
  15. data/app/assets/javascripts/pure_admin/partial_refresh.js +92 -0
  16. data/app/assets/javascripts/pure_admin/portlets.js +139 -0
  17. data/app/assets/javascripts/pure_admin/tabs.js +14 -0
  18. data/app/assets/stylesheets/pure_admin.css.scss +23 -0
  19. data/app/assets/stylesheets/pure_admin/_dropdowns.scss +58 -0
  20. data/app/assets/stylesheets/pure_admin/_tabs.scss +76 -0
  21. data/app/assets/stylesheets/pure_admin/auth.css.scss +22 -0
  22. data/app/assets/stylesheets/pure_admin/breadcrumbs.css.scss +69 -0
  23. data/app/assets/stylesheets/pure_admin/buttons.css.scss +48 -0
  24. data/app/assets/stylesheets/pure_admin/details_panels.css.scss +99 -0
  25. data/app/assets/stylesheets/pure_admin/flash_messages.css.scss +97 -0
  26. data/app/assets/stylesheets/pure_admin/forms.css.scss +129 -0
  27. data/app/assets/stylesheets/pure_admin/inputs/select.css.scss +99 -0
  28. data/app/assets/stylesheets/pure_admin/jquery.tagsinput.css.scss +67 -0
  29. data/app/assets/stylesheets/pure_admin/main_menu.css.scss +146 -0
  30. data/app/assets/stylesheets/pure_admin/modals.css.scss +122 -0
  31. data/app/assets/stylesheets/pure_admin/pagination.css.scss +67 -0
  32. data/app/assets/stylesheets/pure_admin/portlets.css.scss +154 -0
  33. data/app/assets/stylesheets/pure_admin/scopes.css.scss +44 -0
  34. data/app/assets/stylesheets/pure_admin/shell.css.scss +222 -0
  35. data/app/assets/stylesheets/pure_admin/side_menu.css.scss +70 -0
  36. data/app/assets/stylesheets/pure_admin/table_filters.css.scss +90 -0
  37. data/app/assets/stylesheets/pure_admin/tables.css.scss +70 -0
  38. data/app/assets/stylesheets/pure_admin/tags.css.scss +37 -0
  39. data/app/assets/stylesheets/pure_admin/utilities.css.scss +24 -0
  40. data/app/assets/stylesheets/pure_admin/variables.css.scss +38 -0
  41. data/app/helpers/pure_admin/application_helper.rb +12 -0
  42. data/app/helpers/pure_admin/button_helper.rb +58 -0
  43. data/app/helpers/pure_admin/details_panel_helper.rb +121 -0
  44. data/app/helpers/pure_admin/dropdown_helper.rb +40 -0
  45. data/app/helpers/pure_admin/menu_helper.rb +120 -0
  46. data/app/helpers/pure_admin/portlet_helper.rb +75 -0
  47. data/app/helpers/pure_admin/table_filters_helper.rb +158 -0
  48. data/app/inputs/addon_input.rb +17 -0
  49. data/app/inputs/collection_select_input.rb +17 -0
  50. data/app/inputs/email_input.rb +5 -0
  51. data/app/inputs/tel_input.rb +5 -0
  52. data/lib/generators/pure_admin/layout/USAGE +10 -0
  53. data/lib/generators/pure_admin/layout/layout_generator.rb +8 -0
  54. data/lib/generators/pure_admin/layout/templates/admin.css.scss +8 -0
  55. data/lib/generators/pure_admin/layout/templates/admin.html.erb +105 -0
  56. data/lib/generators/pure_admin/scaffold/USAGE +11 -0
  57. data/lib/generators/pure_admin/scaffold/scaffold_generator.rb +66 -0
  58. data/lib/generators/pure_admin/scaffold/templates/_form.html.erb +12 -0
  59. data/lib/generators/pure_admin/scaffold/templates/_show.html.erb +11 -0
  60. data/lib/generators/pure_admin/scaffold/templates/_table.html.erb +21 -0
  61. data/lib/generators/pure_admin/scaffold/templates/models_controller.rb +69 -0
  62. data/lib/generators/pure_admin/simple_form/USAGE +8 -0
  63. data/lib/generators/pure_admin/simple_form/simple_form_generator.rb +7 -0
  64. data/lib/pure-admin-rails.rb +8 -0
  65. data/lib/pure-admin-rails/version.rb +5 -0
  66. metadata +261 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2e7b3065a35d3f75ded4fa531de494100f54d934
4
+ data.tar.gz: b966fa106742cdba9b3671e1ac1cef23c091f6e8
5
+ SHA512:
6
+ metadata.gz: a165071ff0c55c59a8890fa0d47f8f346dec5c4ed2041772bcdc1d86b6047a3bd3782c99cb20a7370e83366e26a060f6f3f20c92585ad5216bd556b854ba5c78
7
+ data.tar.gz: bc6c3ddafc4d6041709a481b0df665940e5e77ed5f82b9b993b7d3f35b848ffcad398655a42831a1bda7de2ff7366ec190832e3c2314470559a9053524aeab30
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Grant Colegate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,131 @@
1
+ # pure-admin-rails
2
+
3
+ [![Build Status](https://travis-ci.org/blaknite/pure-admin-rails.svg?branch=master)](https://travis-ci.org/blaknite/pure-admin-rails)
4
+
5
+ Pure CSS Admin Template for Rails 4+.
6
+
7
+ Forms work with SimpleForm, breadcrumbs with crumpet.
8
+
9
+ ## Installation
10
+
11
+ Add these lines to your Gemfile
12
+ ```ruby
13
+ # Admin theme + dependencies
14
+ gem 'pure-admin-rails', github: 'blaknite/pure-admin-rails', branch: 'master'
15
+ gem 'pure-css-reset-rails', github: 'blaknite/pure-css-reset-rails', branch: 'master'
16
+ gem 'exo2-rails', github: 'blaknite/exo2-rails', branch: 'master'
17
+ gem 'crummy', github: 'blaknite/crummy', branch: 'master'
18
+ gem 'font-awesome-rails'
19
+ gem 'select2-rails'
20
+ gem 'pure-css-rails'
21
+ ```
22
+
23
+ Run
24
+ ```console
25
+ rails generate pure_admin:layout
26
+ rails generate pure_admin:simple_form
27
+ ```
28
+
29
+ Then edit ```app/views/layouts/admin.html.erb``` to your liking.
30
+
31
+ ## Dependencies
32
+
33
+ - Pure CSS
34
+ - jQuery
35
+ - waypoints.js
36
+ - [Select2](https://select2.github.io/)
37
+
38
+ ## Usage
39
+
40
+ ### Portlets
41
+
42
+ Portlets are optionally collapsable containers that can be passed a block, or a source URL.
43
+
44
+ #### Simple Portlets
45
+
46
+ The simplest incarnation of a portlet is,
47
+ ```erb
48
+ <%= portlet do %>
49
+ <p>Hello, world</p>
50
+ <% end %>
51
+ ```
52
+ <img src="readme-assets/simple-portlet.png" width="100%">
53
+
54
+ You may also give a title to portlets.
55
+ ```erb
56
+ <%= portlet 'Greeting' do %>
57
+ <p>Hello, world</p>
58
+ <% end %>
59
+ ```
60
+ <img src="readme-assets/simple-portlet-with-title.png" width="100%">
61
+
62
+ Titles can have [icons](https://fortawesome.github.io/Font-Awesome/icons/), too.
63
+ ```erb
64
+ <%= portlet 'Greeting', icon: 'hand-peace-o' do %>
65
+ <p>Hello, world</p>
66
+ <% end %>
67
+ ```
68
+ <img src="readme-assets/simple-portlet-with-icon.png" width="100%">
69
+
70
+ To make a portlet collapsable, add the `expand: true` option to the `portlet` method.
71
+ ```erb
72
+ <%= portlet 'Greeting', icon: 'hand-peace-o', expand: true do %>
73
+ <p>Hello, world</p>
74
+ <% end %>
75
+ ```
76
+ <img src="readme-assets/simple-portlet-expanded.png" width="100%">
77
+
78
+ If you want the portlet to be collapsed by default, simply add `expand: false` instead.
79
+ <img src="readme-assets/simple-portlet-collapsed.png" width="100%">
80
+
81
+ Any other options that can be passed to Rails' `content_tag` are respected on the portlet too, for example:
82
+
83
+ ```erb
84
+ <%= portlet 'Greeting', class: 'is-supported' do %>
85
+ ...
86
+ <%= portlet 'Greeting', data: { attributes: 'are-too' } do %>
87
+ ...
88
+ ```
89
+
90
+ #### Source Portlets
91
+
92
+ Source portlets are given a source URL which, when expanded, will fetch the content at this URL and display it within the portlet body.
93
+
94
+ Source portlets require a title be given, to give the user somewhere to click to expand.
95
+
96
+ For this example, the following file was created:
97
+ ```html
98
+ <!-- public/test.html -->
99
+ <h2>Congratulations!</h2>
100
+ <p>This page was loaded via AJAX.</p>
101
+ ```
102
+
103
+ ```erb
104
+ <%= portlet 'Source Portlet', source: '/test' %>
105
+ ```
106
+ <img src="readme-assets/source-portlet.png" width="100%">
107
+
108
+ When the portlet is clicked, the content at the source URL will be retrieved and displayed in the body.
109
+ <img src="readme-assets/source-portlet-expanded.png" width="100%">
110
+
111
+ If the AJAX request begins to take too long, the portlet will assume a loading state.
112
+ <img src="readme-assets/source-portlet-loading.png" width="100%">
113
+
114
+ Like Simple Portlets, Source Portlets can be expanded by default.
115
+ The difference however, is that this loading happens when the document is ready.
116
+ To enable this, simply add the familiar `expand: true` to the options.
117
+ ```erb
118
+ <%= portlet 'Source Portlet', source: '/test', expand: true %>
119
+ ```
120
+
121
+ You can additionally expand a portlet via the URL string.
122
+ If you add a class to the portlet you can then target this with a hash at the end of your URL.
123
+ When this is loaded, a portlet with a class that is the same as the hash will be expanded.
124
+
125
+ ```erb
126
+ <%= portlet 'Source Portlet', source: '/test', class: 'source-test' %>
127
+ ```
128
+
129
+ ```console
130
+ http://localhost:3000/{page}#source-test
131
+ ```
@@ -0,0 +1,6 @@
1
+ //= require jquery.throttledebounce
2
+ //= require jquery.waypoints
3
+ //= require_tree ./pure_admin
4
+
5
+ var PureAdmin = PureAdmin || {};
6
+ PureAdmin.LOADING_TIMEOUT = 300;
@@ -0,0 +1,178 @@
1
+ var PureAdmin = PureAdmin || {};
2
+
3
+ PureAdmin.dropdown = {
4
+ // Enable drop-down menus in Pure
5
+ // Inspired by YUI3 gallery-simple-menu by Julien LeComte
6
+ // [https://github.com/yui/yui3-gallery/blob/master/src/gallery-simple-menu/js/simple-menu.js]
7
+
8
+ PureDropdown: function(dropdownParent) {
9
+ var PREFIX = 'pure-',
10
+ ACTIVE_CLASS_NAME = PREFIX + 'menu-active',
11
+ ARIA_ROLE = 'role',
12
+ ARIA_HIDDEN = 'aria-hidden',
13
+ MENU_OPEN = 0,
14
+ MENU_CLOSED = 1,
15
+ MENU_PARENT_CLASS_NAME = 'pure-menu-has-children',
16
+ MENU_ACTIVE_SELECTOR = '.pure-menu-active',
17
+ MENU_LINK_SELECTOR = '.pure-menu-link',
18
+ MENU_SELECTOR = '.pure-menu-children',
19
+ DISMISS_EVENT = (window.hasOwnProperty &&
20
+ window.hasOwnProperty('ontouchstart')) ?
21
+ 'touchstart' : 'mousedown',
22
+
23
+ ARROW_KEYS_ENABLED = true,
24
+
25
+ ddm = this; // drop down menu
26
+
27
+ dropdownParent.classList.add('initialized');
28
+
29
+ this._state = MENU_CLOSED;
30
+
31
+ this.show = function () {
32
+ if (this._state !== MENU_OPEN) {
33
+ this._dropdownParent.classList.add(ACTIVE_CLASS_NAME);
34
+ this._menu.setAttribute(ARIA_HIDDEN, false);
35
+ this._state = MENU_OPEN;
36
+ }
37
+ };
38
+
39
+ this.hide = function () {
40
+ if (this._state !== MENU_CLOSED) {
41
+ this._dropdownParent.classList.remove(ACTIVE_CLASS_NAME);
42
+ this._menu.setAttribute(ARIA_HIDDEN, true);
43
+ this._link.focus();
44
+ this._state = MENU_CLOSED;
45
+ }
46
+ };
47
+
48
+ this.toggle = function () {
49
+ this[this._state === MENU_CLOSED ? 'show' : 'hide']();
50
+ };
51
+
52
+ this.halt = function (e) {
53
+ e.stopPropagation();
54
+ e.preventDefault();
55
+ };
56
+
57
+ this._dropdownParent = dropdownParent;
58
+ this._link = this._dropdownParent.querySelector(MENU_LINK_SELECTOR);
59
+ this._menu = this._dropdownParent.querySelector(MENU_SELECTOR);
60
+ this._firstMenuLink = this._menu.querySelector(MENU_LINK_SELECTOR);
61
+
62
+ // Set ARIA attributes
63
+ this._link.setAttribute('aria-haspopup', 'true');
64
+ this._menu.setAttribute(ARIA_ROLE, 'menu');
65
+ this._menu.setAttribute('aria-labelledby', this._link.getAttribute('id'));
66
+ this._menu.setAttribute('aria-hidden', 'true');
67
+ [].forEach.call(
68
+ this._menu.querySelectorAll('li'),
69
+ function(el){
70
+ el.setAttribute(ARIA_ROLE, 'presentation');
71
+ }
72
+ );
73
+ [].forEach.call(
74
+ this._menu.querySelectorAll('a'),
75
+ function(el){
76
+ el.setAttribute(ARIA_ROLE, 'menuitem');
77
+ }
78
+ );
79
+
80
+ // Toggle on click
81
+ this._link.addEventListener('click', function (e) {
82
+ e.stopPropagation();
83
+ e.preventDefault();
84
+ ddm.toggle();
85
+ });
86
+
87
+ // Keyboard navigation
88
+ document.addEventListener('keydown', function (e) {
89
+ var currentLink,
90
+ previousSibling,
91
+ nextSibling,
92
+ previousLink,
93
+ nextLink;
94
+
95
+ // if the menu isn't active, ignore
96
+ if (ddm._state !== MENU_OPEN) {
97
+ return;
98
+ }
99
+
100
+ // if the menu is the parent of an open, active submenu, ignore
101
+ if (ddm._menu.querySelector(MENU_ACTIVE_SELECTOR)) {
102
+ return;
103
+ }
104
+
105
+ currentLink = ddm._menu.querySelector(':focus');
106
+
107
+ // Dismiss an open menu on ESC
108
+ if (e.keyCode === 27) {
109
+ /* Esc */
110
+ ddm.halt(e);
111
+ ddm.hide();
112
+ }
113
+ // Go to the next link on down arrow
114
+ else if (ARROW_KEYS_ENABLED && e.keyCode === 40) {
115
+ /* Down arrow */
116
+ ddm.halt(e);
117
+ // get the nextSibling (an LI) of the current link's LI
118
+ nextSibling = (currentLink) ? currentLink.parentNode.nextSibling : null;
119
+ // if the nextSibling is a text node (not an element), go to the next one
120
+ while (nextSibling && nextSibling.nodeType !== 1) {
121
+ nextSibling = nextSibling.nextSibling;
122
+ }
123
+ nextLink = (nextSibling) ? nextSibling.querySelector('.pure-menu-link') : null;
124
+ // if there is no currently focused link, focus the first one
125
+ if (!currentLink) {
126
+ ddm._menu.querySelector('.pure-menu-link').focus();
127
+ }
128
+ else if (nextLink) {
129
+ nextLink.focus();
130
+ }
131
+ }
132
+ // Go to the previous link on up arrow
133
+ else if (ARROW_KEYS_ENABLED && e.keyCode === 38) {
134
+ /* Up arrow */
135
+ ddm.halt(e);
136
+ // get the currently focused link
137
+ previousSibling = (currentLink) ? currentLink.parentNode.previousSibling : null;
138
+ while (previousSibling && previousSibling.nodeType !== 1) {
139
+ previousSibling = previousSibling.previousSibling;
140
+ }
141
+ previousLink = (previousSibling) ? previousSibling.querySelector('.pure-menu-link') : null;
142
+ // if there is no currently focused link, focus the last link
143
+ if (!currentLink) {
144
+ ddm._menu.querySelector('.pure-menu-item:last-child .pure-menu-link').focus();
145
+ }
146
+ // else if there is a previous item, go to the previous item
147
+ else if (previousLink) {
148
+ previousLink.focus();
149
+ }
150
+ }
151
+ });
152
+
153
+ // Dismiss an open menu on outside event
154
+ document.addEventListener(DISMISS_EVENT, function (e) {
155
+ var target = e.target;
156
+ if (target !== ddm._link && !ddm._menu.contains(target)) {
157
+ ddm.hide();
158
+ ddm._link.blur();
159
+ }
160
+ });
161
+
162
+ },
163
+
164
+ initDropdowns: function() {
165
+ var dropdownParents = document.querySelectorAll('.pure-menu-has-children:not(.initialized)');
166
+ for (var i = 0; i < dropdownParents.length; i++) {
167
+ var ddm = new PureAdmin.dropdown.PureDropdown(dropdownParents[i]);
168
+ }
169
+ }
170
+ };
171
+
172
+ $(document).ready(function(context) {
173
+ PureAdmin.dropdown.initDropdowns();
174
+ });
175
+
176
+ $(document).on('ajaxSuccess', function(context) {
177
+ PureAdmin.dropdown.initDropdowns();
178
+ });
@@ -0,0 +1,13 @@
1
+ var PureAdmin = PureAdmin || {};
2
+
3
+ PureAdmin.flashMessages = {
4
+ create: function(type, message) {
5
+ $('#flashes').prepend('<div class="flash ' + type + '">' + message + '</div>');
6
+ $('#flashes .flash:not(.bound-close)').addClass('bound-close')
7
+ .on('click', PureAdmin.flashMessages.destroy);
8
+ },
9
+
10
+ destroy: function(event) {
11
+ $(event.target).closest('.flash').remove();
12
+ }
13
+ };
@@ -0,0 +1,24 @@
1
+ var PureAdmin = PureAdmin || {};
2
+
3
+ PureAdmin.inputs = {
4
+ initAll: function(context) {
5
+ for (var inputType in PureAdmin.inputs) {
6
+ inputTypeObj = PureAdmin.inputs[inputType];
7
+ if (typeof(inputTypeObj) === 'object') {
8
+ inputTypeObj.init();
9
+ }
10
+ }
11
+ }
12
+ };
13
+
14
+ $(document).ready(function(context) {
15
+ PureAdmin.inputs.initAll(context);
16
+ });
17
+
18
+ $(document).on('ajaxSuccess', function(context) {
19
+ PureAdmin.inputs.initAll(context);
20
+ });
21
+
22
+ $(document).on('turbolinks:load', function(context) {
23
+ PureAdmin.inputs.initAll(context);
24
+ });
@@ -0,0 +1,21 @@
1
+ if (!PureAdmin) {
2
+ console.error('You must load the PureAdmin JavaScript first before loading this JavaScript.');
3
+ }
4
+
5
+ PureAdmin.inputs.select = {
6
+ init: function(context) {
7
+ $('.pure-admin-select').select2({
8
+ theme: 'pure-admin',
9
+ templateResult: PureAdmin.inputs.select.formatResult,
10
+ templateSelection: PureAdmin.inputs.select.formatResult,
11
+
12
+ escapeMarkup: function(markup) {
13
+ return markup;
14
+ },
15
+ });
16
+ },
17
+
18
+ formatResult: function(result) {
19
+ return result.name || result.text || '<span class="text-muted">(blank)</span>';
20
+ }
21
+ };
@@ -0,0 +1,21 @@
1
+ var PureAdmin = PureAdmin || {};
2
+
3
+ PureAdmin.header = {
4
+ ready: function() {
5
+ $('#wrap').waypoint(function(direction) {
6
+ $('#back-to-top').toggle(direction === 'down');
7
+ }, { offset: -300 });
8
+
9
+ $('#wrap').waypoint(function(direction) {
10
+ $('#wrap').toggleClass('no-header', direction === 'down');
11
+ }, { offset: -48 });
12
+
13
+ $('#back-to-top').on('click', $.debounce(1000, true, function() {
14
+ $("html, body").animate({ scrollTop: 0 }, 300);
15
+ $('#wrap').removeClass('no-header');
16
+ }));
17
+ }
18
+ };
19
+
20
+ $(document).ready(PureAdmin.header.ready)
21
+ $(document).on('turbolinks:load', PureAdmin.header.ready)
@@ -0,0 +1,108 @@
1
+ var PureAdmin = PureAdmin || {};
2
+
3
+ PureAdmin.mainMenu = {
4
+ scroll: function(element, event) {
5
+ var menu = element.find('> nav');
6
+ var menuList = menu.find('> .pure-menu-list');
7
+
8
+ // do not scroll if list is shorter than document
9
+ if ( menuList.width() < $(document).width() ) return;
10
+
11
+ // determine which scroll button was clicked
12
+ var direction = $(event.target).closest('.fade-left, .fade-right').data('direction');
13
+
14
+ // determine how far to scroll each click and the extremes of scrolling
15
+ var maxOffset = menuList.width() - $(document).width();
16
+ var minStep = $(document).width() / 3;
17
+ var offset = maxOffset / 4;
18
+ if ( maxOffset < minStep ) offset = maxOffset;
19
+ if ( offset < minStep ) offset = minStep;
20
+
21
+ if ( direction == 'left' ) {
22
+ // we're scrolling left
23
+ if ( menu.scrollLeft() - offset < offset / 2 ) {
24
+ menu.animate({ scrollLeft: 0 }, 100);
25
+ } else {
26
+ menu.animate({ scrollLeft: menu.scrollLeft() - offset }, 100);
27
+ }
28
+ } else if ( direction == 'right' ) {
29
+ // we're scrolling right
30
+ if ( menu.scrollLeft() + offset > maxOffset - offset / 2 ) {
31
+ menu.animate({ scrollLeft: maxOffset }, 300);
32
+ } else {
33
+ menu.animate({ scrollLeft: menu.scrollLeft() + offset }, 100);
34
+ }
35
+ }
36
+ },
37
+
38
+ updateArrows: function(element) {
39
+ var menu = element.find('nav');
40
+ var menuList = menu.find('.pure-menu-list');
41
+ var leftArrow = element.find('.fade-left');
42
+ var rightArrow = element.find('.fade-right');
43
+
44
+ // determine how far to scroll each click and the extremes of scrolling
45
+ var maxOffset = menuList.width() - $(document).width();
46
+
47
+ // toggle the navigation arrows
48
+ rightArrow.toggle(menu.scrollLeft() < maxOffset);
49
+ leftArrow.toggle(menu.scrollLeft() > 0);
50
+ },
51
+
52
+ openSubMenu: function(element) {
53
+ var mainMenu = $('#main-menu');
54
+ var subMenu = $('#sub-menu');
55
+ var subMenuContent = element.find('> .sub-menu').clone() || '';
56
+
57
+ mainMenu.addClass('navigating').find('.pure-menu-item').removeClass('menu-active');
58
+ mainMenu.find('.pure-menu-link').off('click', PureAdmin.mainMenu.closeSubMenu);
59
+ if ( subMenuContent.length > 0 ) {
60
+ element.addClass('menu-active');
61
+ element.find('.pure-menu-link').on('click', PureAdmin.mainMenu.closeSubMenu);
62
+ subMenu.removeClass('hidden').find('.pure-menu').html(subMenuContent);
63
+
64
+ PureAdmin.mainMenu.updateArrows(subMenu);
65
+ }
66
+ },
67
+
68
+ closeSubMenu: function() {
69
+ var mainMenu = $('#main-menu');
70
+ var subMenu = $('#sub-menu');
71
+
72
+ subMenu.addClass('hidden').find('.pure-menu').html($('#main-menu .current > .sub-menu').clone());
73
+ mainMenu.removeClass('navigating').find('.pure-menu-item').removeClass('menu-active');
74
+ mainMenu.find('.pure-menu-link').off('click', PureAdmin.mainMenu.closeSubMenu);
75
+ },
76
+
77
+ ready: function() {
78
+ PureAdmin.mainMenu.updateArrows($('#main-menu'));
79
+
80
+ $('*[rel=main-menu-scroll]').on('click', function(event) {
81
+ PureAdmin.mainMenu.scroll($('#main-menu'), event);
82
+ });
83
+
84
+ $('*[rel=sub-menu-scroll]').on('click', function(event) {
85
+ PureAdmin.mainMenu.scroll($('#sub-menu'), event);
86
+ });
87
+
88
+ $('#main-menu nav').on('scroll', function(event) {
89
+ PureAdmin.mainMenu.updateArrows($('#main-menu'));
90
+ });
91
+
92
+ $('#sub-menu nav').on('scroll', function(event) {
93
+ PureAdmin.mainMenu.updateArrows($('#sub-menu'));
94
+ });
95
+
96
+ $('#main-menu .pure-menu-link').on('click', function(event) {
97
+ var element = $(event.target).closest('li');
98
+ PureAdmin.mainMenu.openSubMenu(element);
99
+ });
100
+
101
+ $('#main').on('click', function(event) {
102
+ PureAdmin.mainMenu.closeSubMenu();
103
+ });
104
+ }
105
+ };
106
+
107
+ $(document).ready(PureAdmin.mainMenu.ready)
108
+ $(document).on('turbolinks:load', PureAdmin.mainMenu.ready)