docks_theme_api 1.0.2
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.
- checksums.yaml +15 -0
- data/.babelrc +4 -0
- data/.editorconfig +8 -0
- data/.eslintrc +115 -0
- data/.gitignore +24 -0
- data/.rubocop.yml +20 -0
- data/.travis.yml +16 -0
- data/Gemfile +4 -0
- data/README.md +5 -0
- data/Rakefile +3 -0
- data/assets/images/icons.svg +63 -0
- data/assets/scripts/coffeescript/pattern_library_helpers.coffee +8 -0
- data/assets/scripts/javascript/pattern_library_helpers.js +11 -0
- data/assets/scripts/pattern_library.js +10380 -0
- data/assets/scripts/pattern_library_demo.js +0 -0
- data/assets/styles/less/pattern-library-helpers.less +103 -0
- data/assets/styles/pattern-library-demo.css +1882 -0
- data/assets/styles/pattern-library.css +1882 -0
- data/assets/styles/sass/pattern-library-helpers.sass +90 -0
- data/assets/styles/scss/pattern-library-helpers.scss +99 -0
- data/assets/styles/stylus/pattern-library-helpers.styl +90 -0
- data/assets/templates/erb/demo.erb +26 -0
- data/assets/templates/erb/layouts/demo.erb +17 -0
- data/assets/templates/erb/layouts/pattern.erb +76 -0
- data/assets/templates/erb/partials/sidebar.erb +124 -0
- data/assets/templates/erb/partials/symbols/class.erb +1 -0
- data/assets/templates/erb/partials/symbols/demo.erb +40 -0
- data/assets/templates/erb/partials/symbols/factory.erb +70 -0
- data/assets/templates/erb/partials/symbols/function.erb +103 -0
- data/assets/templates/erb/partials/symbols/mixin.erb +62 -0
- data/assets/templates/erb/partials/symbols/variable.erb +59 -0
- data/assets/templates/erb/pattern.erb +102 -0
- data/assets/templates/haml/demo.haml +14 -0
- data/assets/templates/haml/layouts/demo.haml +6 -0
- data/assets/templates/haml/layouts/pattern.haml +38 -0
- data/assets/templates/haml/partials/sidebar.haml +68 -0
- data/assets/templates/haml/partials/symbols/class.haml +1 -0
- data/assets/templates/haml/partials/symbols/demo.haml +23 -0
- data/assets/templates/haml/partials/symbols/factory.haml +38 -0
- data/assets/templates/haml/partials/symbols/function.haml +54 -0
- data/assets/templates/haml/partials/symbols/mixin.haml +31 -0
- data/assets/templates/haml/partials/symbols/variable.haml +22 -0
- data/assets/templates/haml/pattern.haml +54 -0
- data/assets/templates/slim/demo.slim +24 -0
- data/assets/templates/slim/layouts/demo.slim +5 -0
- data/assets/templates/slim/layouts/pattern.slim +48 -0
- data/assets/templates/slim/partials/sidebar.slim +112 -0
- data/assets/templates/slim/partials/symbols/class.slim +1 -0
- data/assets/templates/slim/partials/symbols/demo.slim +30 -0
- data/assets/templates/slim/partials/symbols/factory.slim +57 -0
- data/assets/templates/slim/partials/symbols/function.slim +81 -0
- data/assets/templates/slim/partials/symbols/mixin.slim +45 -0
- data/assets/templates/slim/partials/symbols/variable.slim +35 -0
- data/assets/templates/slim/pattern.slim +63 -0
- data/docks_config.rb +32 -0
- data/docks_theme_api.gemspec +37 -0
- data/gulpfile.js +88 -0
- data/karma.conf.js +6 -0
- data/lib/docks_theme_api/components/base_component.rb +99 -0
- data/lib/docks_theme_api/components/code_block_component.rb +10 -0
- data/lib/docks_theme_api/components/popover_component.rb +15 -0
- data/lib/docks_theme_api/components/table_component.rb +34 -0
- data/lib/docks_theme_api/components/tablist_component.rb +11 -0
- data/lib/docks_theme_api/components.rb +21 -0
- data/lib/docks_theme_api/helpers/ui_helper.rb +69 -0
- data/lib/docks_theme_api/theme.rb +21 -0
- data/lib/docks_theme_api.rb +1 -0
- data/package.json +60 -0
- data/source/behaviors/filterable/filterable.coffee +353 -0
- data/source/behaviors/filterable/filterable.js +0 -0
- data/source/behaviors/filterable/filterable.scss +34 -0
- data/source/behaviors/filterable/package.json +3 -0
- data/source/behaviors/index.js +0 -0
- data/source/components/avatar/avatar.erb +20 -0
- data/source/components/avatar/avatar.js +142 -0
- data/source/components/avatar/avatar.scss +200 -0
- data/source/components/avatar/avatar_container.erb +13 -0
- data/source/components/avatar/package.json +3 -0
- data/source/components/avatar/spec/avatar_spec.js +81 -0
- data/source/components/badge/badge.scss +158 -0
- data/source/components/button/button.scss +213 -0
- data/source/components/card/card.scss +32 -0
- data/source/components/code_block/code-block.scss +353 -0
- data/source/components/code_block/code_block.erb +95 -0
- data/source/components/code_block/code_block.js +444 -0
- data/source/components/code_block/package.json +3 -0
- data/source/components/code_block/spec/code_block_spec.js +10 -0
- data/source/components/demo/demo.js +244 -0
- data/source/components/demo/demo.scss +90 -0
- data/source/components/demo/package.json +3 -0
- data/source/components/exploded/exploded.erb +25 -0
- data/source/components/exploded/exploded.js +694 -0
- data/source/components/exploded/exploded.scss +166 -0
- data/source/components/exploded/package.json +3 -0
- data/source/components/field/field.js +24 -0
- data/source/components/field/field.scss +101 -0
- data/source/components/field/package.json +3 -0
- data/source/components/header/header.scss +33 -0
- data/source/components/iframe/iframe.erb +12 -0
- data/source/components/iframe/iframe.js +381 -0
- data/source/components/iframe/package.json +3 -0
- data/source/components/index.js +37 -0
- data/source/components/inline_group/inline-group.scss +14 -0
- data/source/components/internal_link/internal_link.js +49 -0
- data/source/components/internal_link/package.json +3 -0
- data/source/components/list/list.scss +230 -0
- data/source/components/modal/modal.coffee +84 -0
- data/source/components/modal/modal.erb +19 -0
- data/source/components/modal/modal.js +0 -0
- data/source/components/modal/modal.scss +57 -0
- data/source/components/modal/package.json +3 -0
- data/source/components/notice/notice.scss +48 -0
- data/source/components/popover/package.json +3 -0
- data/source/components/popover/popover.coffee +562 -0
- data/source/components/popover/popover.erb +21 -0
- data/source/components/popover/popover.js +0 -0
- data/source/components/popover/popover.scss +139 -0
- data/source/components/range/range.scss +78 -0
- data/source/components/resizable/package.json +3 -0
- data/source/components/resizable/resizable.erb +30 -0
- data/source/components/resizable/resizable.js +250 -0
- data/source/components/resizable/resizable.scss +245 -0
- data/source/components/resizable/size_buttons.js +249 -0
- data/source/components/scroll_container/package.json +3 -0
- data/source/components/scroll_container/scroll-container.scss +4 -0
- data/source/components/scroll_container/scroll_container.js +24 -0
- data/source/components/section/section.scss +99 -0
- data/source/components/select/package.json +3 -0
- data/source/components/select/select.erb +21 -0
- data/source/components/select/select.js +35 -0
- data/source/components/select/select.scss +163 -0
- data/source/components/table/package.json +3 -0
- data/source/components/table/table.erb +16 -0
- data/source/components/table/table.js +351 -0
- data/source/components/table/table.scss +236 -0
- data/source/components/tablist/package.json +3 -0
- data/source/components/tablist/tablist.erb +13 -0
- data/source/components/tablist/tablist.js +246 -0
- data/source/components/tablist/tablist.scss +191 -0
- data/source/components/tablist/tablist_panel.erb +14 -0
- data/source/components/tablist/tablist_tab.erb +20 -0
- data/source/components/toggle/package.json +3 -0
- data/source/components/toggle/toggle.erb +11 -0
- data/source/components/toggle/toggle.js +211 -0
- data/source/components/toggle/toggle_container.erb +30 -0
- data/source/components/vertical_spacer/vertical-spacer.scss +3 -0
- data/source/components/vertical_stack/vertical-stack.scss +19 -0
- data/source/components/xray/package.json +3 -0
- data/source/components/xray/xray.erb +50 -0
- data/source/components/xray/xray.js +123 -0
- data/source/components/xray/xray.scss +79 -0
- data/source/foundation/app/app.js +15 -0
- data/source/foundation/app/package.json +3 -0
- data/source/pattern-library-demo.scss +13 -0
- data/source/pattern-library.scss +13 -0
- data/source/pattern_library.js +8 -0
- data/source/pattern_library_demo.js +8 -0
- data/source/structures/index.js +11 -0
- data/source/structures/sidebar/package.json +3 -0
- data/source/structures/sidebar/sidebar.js +69 -0
- data/source/structures/sidebar/sidebar.scss +79 -0
- data/source/utilities/builder/builder.js +138 -0
- data/source/utilities/builder/package.json +3 -0
- data/source/utilities/client/client.js +7 -0
- data/source/utilities/client/package.json +3 -0
- data/source/utilities/colors/colors.scss +112 -0
- data/source/utilities/defaults/defaults.scss +38 -0
- data/source/utilities/dom_cache/dom_cache.js +24 -0
- data/source/utilities/dom_cache/package.json +3 -0
- data/source/utilities/events/events.js +25 -0
- data/source/utilities/events/package.json +3 -0
- data/source/utilities/font_sizes/font-sizes.scss +85 -0
- data/source/utilities/foundation/a11y.scss +10 -0
- data/source/utilities/foundation/base.scss +29 -0
- data/source/utilities/foundation/icon.scss +114 -0
- data/source/utilities/foundation/layout.scss +67 -0
- data/source/utilities/foundation/page.scss +39 -0
- data/source/utilities/foundation/type.scss +208 -0
- data/source/utilities/functions/functions.scss +127 -0
- data/source/utilities/keycodes/keycodes.js +23 -0
- data/source/utilities/keycodes/package.json +3 -0
- data/source/utilities/markup/markup.js +90 -0
- data/source/utilities/markup/package.json +3 -0
- data/source/utilities/media/media.scss +172 -0
- data/source/utilities/mixins/mixins.scss +89 -0
- data/source/utilities/naming_convention/naming_convention.js +3 -0
- data/source/utilities/naming_convention/package.json +3 -0
- data/source/utilities/numbers/numbers.js +14 -0
- data/source/utilities/numbers/package.json +3 -0
- data/source/utilities/painting/package.json +3 -0
- data/source/utilities/painting/painting.js +7 -0
- data/source/utilities/pattern/package.json +3 -0
- data/source/utilities/pattern/pattern.js +50 -0
- data/source/utilities/query_string/package.json +3 -0
- data/source/utilities/query_string/query_string.js +24 -0
- data/source/utilities/template/package.json +3 -0
- data/source/utilities/template/template.js +10 -0
- data/source/utilities/text_range/package.json +3 -0
- data/source/utilities/text_range/text_range.js +30 -0
- data/source/utilities/ui_events/package.json +3 -0
- data/source/utilities/ui_events/ui_events.js +85 -0
- data/source/utilities/variables/variables.scss +18 -0
- data/source/utilities/z_indexes/z-indexes.scss +88 -0
- data/source/vendor/array_includes.js +28 -0
- data/source/vendor/highlight.js +1142 -0
- data/source/vendor/index.js +1 -0
- data/source/vendor/matrix.js +399 -0
- data/source/vendor/query_string.js +66 -0
- data/spec/assets/.eslintrc +9 -0
- data/spec/assets/spec_fixture.js +33 -0
- data/spec/assets/spec_helper.js +19 -0
- data/spec/lib/components/base_component_spec.rb +156 -0
- data/spec/lib/components_spec.rb +30 -0
- data/spec/lib/helpers/ui_helper_spec.rb +62 -0
- data/spec/lib/theme_spec.rb +25 -0
- data/spec/spec_helper.rb +15 -0
- data/tasks/gulp/.eslintrc +6 -0
- data/tasks/gulp/browser_sync.js +8 -0
- data/tasks/gulp/code_quality/scripts.js +10 -0
- data/tasks/gulp/config/index.js +116 -0
- data/tasks/gulp/minify/scripts.js +13 -0
- data/tasks/gulp/minify/styles.js +13 -0
- data/tasks/gulp/pattern_library/index.js +5 -0
- data/tasks/gulp/pattern_library/scripts.js +10 -0
- data/tasks/gulp/pattern_library/styles.js +10 -0
- data/tasks/gulp/scripts.js +8 -0
- data/tasks/gulp/spec/scripts.js +11 -0
- data/tasks/gulp/styles.js +17 -0
- data/tasks/gulp/utilities/babel/relative_require.js +22 -0
- data/tasks/gulp/utilities/babel/spec_helper.js +20 -0
- data/tasks/gulp/utilities/browserify_bundler.js +22 -0
- data/tasks/gulp/utilities/handle_errors.js +13 -0
- data/tasks/gulp/watch.js +9 -0
- data/tasks/rake/rspec.rake +7 -0
- data/tasks/rake/rubocop.rake +8 -0
- data/tasks/rake/templates.rake +50 -0
- metadata +470 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
// ___ ___ ___ ___
|
2
|
+
// / /\ / /\ / /\ / /\ ___
|
3
|
+
// / /:/_ / /:/_ / /:/_ / /:/ / /\
|
4
|
+
// / /:/ /\ / /:/ /\ ___ ___ / /:/ /\ / /:/ / /:/
|
5
|
+
// / /:/ /::\ / /:/ /:/_/__/\ / /\/ /:/ /:/_ / /:/ ___ / /:/
|
6
|
+
// /__/:/ /:/\:\/__/:/ /:/ /\ \:\ / /:/__/:/ /:/ /\/__/:/ / /\/ /::\
|
7
|
+
// \ \:\/:/~/:/\ \:\/:/ /:/\ \:\ /:/\ \:\/:/ /:/\ \:\ / /:/__/:/\:\
|
8
|
+
// \ \::/ /:/ \ \::/ /:/ \ \:\/:/ \ \::/ /:/ \ \:\ /:/\__\/ \:\
|
9
|
+
// \__\/ /:/ \ \:\/:/ \ \::/ \ \:\/:/ \ \:\/:/ \ \:\
|
10
|
+
// /__/:/ \ \::/ \__\/ \ \::/ \ \::/ \__\/
|
11
|
+
// \__\/ \__\/ \__\/ \__\/
|
12
|
+
|
13
|
+
//*
|
14
|
+
// @pattern Select
|
15
|
+
//
|
16
|
+
// A custom `select` element. In order to present these in the same way across
|
17
|
+
// browsers, most of the styling is done on a node wrapped around an actual
|
18
|
+
// `select` element, and a bit of JavaScript that translates the focus/ blur
|
19
|
+
// on the contained `select` into a state class.
|
20
|
+
//
|
21
|
+
// @since 1.0.0
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
$select--font-size: (font-size(control) * 0.9);
|
26
|
+
$select--horizontal-padding: default(control-padding);
|
27
|
+
$select--line-height: default(control-size);
|
28
|
+
$select--icon-size: $select--font-size / 1.6;
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
//*
|
33
|
+
// The wrapper around a `select`. This wrapper provides most of the visual
|
34
|
+
// styling, including the focus styling. This part of the component also
|
35
|
+
// creates a triangle icon in place of the browser-supplied one.
|
36
|
+
//
|
37
|
+
// @helper
|
38
|
+
// <%= docks_select options: %w(Super_long_option_that_is_quite_long normal_size SMALL) %>
|
39
|
+
|
40
|
+
.select {
|
41
|
+
// position
|
42
|
+
position: relative;
|
43
|
+
|
44
|
+
// box model
|
45
|
+
display: inline-block;
|
46
|
+
|
47
|
+
// backdrop
|
48
|
+
border-radius: default(border-radius);
|
49
|
+
background-color: ui-color(gray);
|
50
|
+
|
51
|
+
&:after {
|
52
|
+
content: "";
|
53
|
+
|
54
|
+
// position
|
55
|
+
position: absolute;
|
56
|
+
right: $select--horizontal-padding;
|
57
|
+
top: 50%;
|
58
|
+
transform: rotate(45deg);
|
59
|
+
|
60
|
+
// box model
|
61
|
+
display: block;
|
62
|
+
height: $select--icon-size;
|
63
|
+
width: $select--icon-size;
|
64
|
+
margin-top: (-0.75 * $select--icon-size);
|
65
|
+
|
66
|
+
// backdrop
|
67
|
+
border: solid rgba(ui-color(gray, darker), 0.5);
|
68
|
+
border-width: 0 2px 2px 0;
|
69
|
+
pointer-events: none;
|
70
|
+
}
|
71
|
+
|
72
|
+
+ .docks-button {
|
73
|
+
margin-left: half(default(spacing));
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
//*
|
78
|
+
// This state is applied to a `select` whose contained input is focused.
|
79
|
+
|
80
|
+
.select--is-focused {
|
81
|
+
border-color: color(blue);
|
82
|
+
}
|
83
|
+
|
84
|
+
//*
|
85
|
+
// A select that should be displayed in a monospace font (for example, because
|
86
|
+
// it is choosing a class name).
|
87
|
+
|
88
|
+
.select--code {
|
89
|
+
> .select__input {
|
90
|
+
@include type--monospace-font-family;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
//*
|
97
|
+
// The actual `select`. Most of the styles here go to undoing the default
|
98
|
+
// browser styles for `select`s. All of the font sizing for the component must
|
99
|
+
// be placed here for those styles to display correctly.
|
100
|
+
|
101
|
+
.select__input {
|
102
|
+
// box model
|
103
|
+
@include remove-browser-styling;
|
104
|
+
box-sizing: border-box;
|
105
|
+
display: block;
|
106
|
+
width: 100%;
|
107
|
+
max-width: none;
|
108
|
+
height: auto;
|
109
|
+
padding: 0 (double($select--horizontal-padding) + $select--icon-size) 0 $select--horizontal-padding;
|
110
|
+
|
111
|
+
// backdrop
|
112
|
+
background: transparent;
|
113
|
+
border: none;
|
114
|
+
|
115
|
+
// type
|
116
|
+
font-size: $select--font-size;
|
117
|
+
line-height: default(control-size);
|
118
|
+
font-family: inherit;
|
119
|
+
color: ui-color(gray, darker);
|
120
|
+
// font-family: Consolas, monospace;
|
121
|
+
|
122
|
+
&:focus {
|
123
|
+
outline: none;
|
124
|
+
border: none;
|
125
|
+
}
|
126
|
+
|
127
|
+
> option {
|
128
|
+
color: color(slate);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
// All of the below hacks courtesy of Todd Parker's fine worK here:
|
133
|
+
// http://jsbin.com / yaruh / 49 / edit
|
134
|
+
|
135
|
+
// Hides native select arrow in IE 10+
|
136
|
+
_:-ms-input-placeholder, :root .select__input::-ms-expand {
|
137
|
+
display: none;
|
138
|
+
}
|
139
|
+
|
140
|
+
// Hides blue background on focus in IE 10+
|
141
|
+
_:-ms-input-placeholder, :root .select__input:focus::-ms-value {
|
142
|
+
background: transparent;
|
143
|
+
}
|
144
|
+
|
145
|
+
// Crazy hacks to target FF and clip the native select arrow
|
146
|
+
@supports (-moz-appearance:meterbar) and (background-blend-mode:difference,normal) {
|
147
|
+
|
148
|
+
_::-moz-progress-bar,
|
149
|
+
body:last-child .select__input__wrapper {
|
150
|
+
overflow: hidden;
|
151
|
+
}
|
152
|
+
|
153
|
+
_::-moz-progress-bar,
|
154
|
+
body:last-child .select__input {
|
155
|
+
width: calc(100% + 30px);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
// Kills the stupid focus ring in FF
|
160
|
+
.select__input:-moz-focusring {
|
161
|
+
color: transparent;
|
162
|
+
text-shadow: 0 0 0 black;
|
163
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div class="table__container">
|
2
|
+
<div class="table__actions">
|
3
|
+
<div class="docks-button__segmented-container">
|
4
|
+
<button class="docks-button" table-action="shift-left" style="font-family: Consolas;"><</button>
|
5
|
+
<button class="docks-button" table-action="shift-right" style="font-family: Consolas;">></button>
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="table__backdrop">
|
10
|
+
<div class="table__scroller">
|
11
|
+
<table class="table">
|
12
|
+
<%= capture(table, &table.block) %>
|
13
|
+
</table>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -0,0 +1,351 @@
|
|
1
|
+
import Builder from "~utilities/builder";
|
2
|
+
import Keycodes from "~utilities/keycodes";
|
3
|
+
|
4
|
+
const classes = {
|
5
|
+
root: "table",
|
6
|
+
header: "table__header",
|
7
|
+
body: "table__body",
|
8
|
+
row: "table__row",
|
9
|
+
cell: "table__cell",
|
10
|
+
scroller: "table__scroller",
|
11
|
+
container: "table__container",
|
12
|
+
actions: "table__actions"
|
13
|
+
};
|
14
|
+
|
15
|
+
const states = {
|
16
|
+
scroller: { scrolled: "table__scroller--is-scrolled" },
|
17
|
+
container: { overflowing: "table__container--is-overflowing" }
|
18
|
+
};
|
19
|
+
|
20
|
+
const attrs = {
|
21
|
+
action: "table-action"
|
22
|
+
};
|
23
|
+
|
24
|
+
const actions = {
|
25
|
+
shift_right: "shift-right",
|
26
|
+
shift_left: "shift-left"
|
27
|
+
};
|
28
|
+
|
29
|
+
var Table, cache_preferred_widths, check_for_overflow, shift_table_right,
|
30
|
+
shift_table_left, last_visible_cell, handle_keypress, handle_scroll,
|
31
|
+
initialize_table_actions, update_actions;
|
32
|
+
|
33
|
+
//*
|
34
|
+
// Calculates and applies the intrinsic widths of the columns of a `table`,
|
35
|
+
// keeping in mind the effective maximum column size implied by the `min-width`
|
36
|
+
// set on the table.
|
37
|
+
//
|
38
|
+
// The intrinsic widths of each column are applied only once, to the header
|
39
|
+
// cells of the column. These are applied by using them as the `min-width`s for
|
40
|
+
// each header cell, so that the table will appropriately overflow once the
|
41
|
+
// space available to the table is less than the sum of its intrinsic widths.
|
42
|
+
//
|
43
|
+
// A side effect of this function is that `self` is augmented with the minimum
|
44
|
+
// total intrinsic width of its columns (`min_width`).
|
45
|
+
//
|
46
|
+
// @param {Object} self - The internal details of a `Table`.
|
47
|
+
// @private
|
48
|
+
|
49
|
+
cache_preferred_widths = (self) => {
|
50
|
+
var table = self.root,
|
51
|
+
clone = table.parentNode.parentNode.cloneNode(true),
|
52
|
+
width_calculation_container, clone_table, cloned_header_cells;
|
53
|
+
|
54
|
+
// For the purposes of the width calculations, let the table be at the smaller
|
55
|
+
// of its intrinsic size and the `min-width` set in CSS.
|
56
|
+
clone.style.maxWidth = window.getComputedStyle(table).minWidth;
|
57
|
+
table.style.minWidth = "0px";
|
58
|
+
clone.style.display = "inline-block";
|
59
|
+
|
60
|
+
// Creates a container that won't restrict the size of the table.
|
61
|
+
width_calculation_container = $("<div style='width: 10000px; visibility: hidden; height: 0;' />")[0];
|
62
|
+
width_calculation_container.appendChild(clone);
|
63
|
+
document.body.appendChild(width_calculation_container);
|
64
|
+
|
65
|
+
clone_table = clone.querySelector(`.${classes.root}`);
|
66
|
+
self.min_width = clone_table.offsetWidth; // sum of constrained intrinsic widths
|
67
|
+
|
68
|
+
// Apply the constrained intrinsic widths to each of the header cells in the
|
69
|
+
// actual table.
|
70
|
+
cloned_header_cells = Array.from(clone.querySelectorAll(`.${classes.header} .${classes.cell}`));
|
71
|
+
self.header_cells.forEach((cell, index) => {
|
72
|
+
cell.style.minWidth = `${cloned_header_cells[index].offsetWidth}px`;
|
73
|
+
});
|
74
|
+
|
75
|
+
// Cleanup.
|
76
|
+
document.body.removeChild(width_calculation_container);
|
77
|
+
};
|
78
|
+
|
79
|
+
//*
|
80
|
+
// Determines whether or not there is overflow and performs all necessary size
|
81
|
+
// and other DOM updates. This includes fixing the size of the first cell in a
|
82
|
+
// row and adding a compensating amount of left padding to the second cell in
|
83
|
+
// each row when the table should overflow, and reversing this when it no longer
|
84
|
+
// needs to do so.
|
85
|
+
//
|
86
|
+
// @param {Object} self - The internal details of a `Table`.
|
87
|
+
// @private
|
88
|
+
|
89
|
+
check_for_overflow = (self) => {
|
90
|
+
var { scroller, root, container, overflowing, min_width } = self,
|
91
|
+
scroller_width = scroller.offsetWidth,
|
92
|
+
first_cell_width, cell, available_space, index;
|
93
|
+
|
94
|
+
if(!scroller_width) { return; }
|
95
|
+
|
96
|
+
// Newly overflowing, get the header's width and apply that same width
|
97
|
+
// to each first cell (since they'll be absolutely positioned), and add an
|
98
|
+
// equivalent amount of left padding to the second cell.
|
99
|
+
if(!overflowing && scroller_width < min_width) {
|
100
|
+
for(cell of Array.from(root.querySelectorAll(`.${classes.cell}:first-child`))) {
|
101
|
+
first_cell_width = first_cell_width || cell.offsetWidth;
|
102
|
+
|
103
|
+
cell.style.width = `${first_cell_width}px`;
|
104
|
+
self.scroller.style.paddingLeft = `${first_cell_width - 1}px`;
|
105
|
+
}
|
106
|
+
|
107
|
+
container.classList.add(states.container.overflowing);
|
108
|
+
self.overflowing = true;
|
109
|
+
}
|
110
|
+
|
111
|
+
// No longer overflowing — reverse what we did before!
|
112
|
+
if(overflowing && scroller_width >= min_width) {
|
113
|
+
for(cell of Array.from(root.querySelectorAll(`.${classes.cell}:first-child`))) {
|
114
|
+
first_cell_width = first_cell_width || cell.offsetWidth;
|
115
|
+
|
116
|
+
cell.style.width = null;
|
117
|
+
self.scroller.style.paddingLeft = null;
|
118
|
+
}
|
119
|
+
|
120
|
+
for(cell of self.header_cells) { cell.style.maxWidth = null; }
|
121
|
+
|
122
|
+
container.classList.remove(states.container.overflowing);
|
123
|
+
self.overflowing = false;
|
124
|
+
}
|
125
|
+
|
126
|
+
// Even if already overflowing, update the max-widths of columns such that the
|
127
|
+
// persistant cell + any other cell <= the total width.
|
128
|
+
if(scroller_width < min_width) {
|
129
|
+
available_space = scroller_width - self.header_cells[0].offsetWidth;
|
130
|
+
|
131
|
+
for(index = 1; index++; index < self.header_cells.length) {
|
132
|
+
self.header_cells[index].style.maxWidth = `${available_space}px`;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
};
|
136
|
+
|
137
|
+
last_visible_cell = (self) => {
|
138
|
+
var last_cell = self.header_cells[1],
|
139
|
+
parent_width = self.scroller.scrollLeft + self.scroller.offsetWidth - parseInt(self.scroller.style.paddingLeft, 10),
|
140
|
+
width_so_far = last_cell.offsetWidth,
|
141
|
+
cell, index;
|
142
|
+
|
143
|
+
for(index = 2; index++; index < self.header_cells[index]) {
|
144
|
+
cell = self.header_cells[index];
|
145
|
+
if((width_so_far + cell.offsetWidth) > parent_width) { break; }
|
146
|
+
last_cell = cell;
|
147
|
+
width_so_far += cell.offsetWidth;
|
148
|
+
}
|
149
|
+
|
150
|
+
return [last_cell, parent_width - width_so_far];
|
151
|
+
};
|
152
|
+
|
153
|
+
//*
|
154
|
+
// Shifts the `Table` represented by `self` to the right by one column. If the
|
155
|
+
// table currently has a column that is partially visible on the right, the
|
156
|
+
// table will be scrolled such that that entire column is visible. If a column
|
157
|
+
// is entirely visible and pressed right against the right edge of the scroll
|
158
|
+
// area, the next (fully hidden) column will be shown.
|
159
|
+
//
|
160
|
+
// This has no effect if the table is already fully scrolled.
|
161
|
+
//
|
162
|
+
// @param {Object} self - The internal details of a `Table`.
|
163
|
+
|
164
|
+
shift_table_right = (self) => {
|
165
|
+
var last_cell, next_cell_overlap;
|
166
|
+
|
167
|
+
if(!self.overflowing) { return; }
|
168
|
+
[last_cell, next_cell_overlap] = last_visible_cell(self);
|
169
|
+
|
170
|
+
if(last_cell === self.header_cells[self.header_cells.length - 1]) { return; }
|
171
|
+
self.scroller.scrollLeft += (last_cell.nextElementSibling.offsetWidth - next_cell_overlap);
|
172
|
+
self.scroller.classList.add(states.scroller.scrolled);
|
173
|
+
update_actions(self);
|
174
|
+
};
|
175
|
+
|
176
|
+
//*
|
177
|
+
// Shifts the `Table` represented by `self` to the left by one column. If the
|
178
|
+
// table currently has a column that is partially visible on the right, the
|
179
|
+
// table will be scrolled such that that entire column is hidden. If a column
|
180
|
+
// is entirely visible and pressed right against the right edge of the scroll
|
181
|
+
// area, that column will be scrolled out of view.
|
182
|
+
//
|
183
|
+
// This has no effect if the table is at a scroll position of 0.
|
184
|
+
//
|
185
|
+
// @param {Object} self - The internal details of a `Table`.
|
186
|
+
|
187
|
+
shift_table_left = (self) => {
|
188
|
+
var last_cell, next_cell_overlap, scroll_delta;
|
189
|
+
|
190
|
+
if(!self.overflowing) { return; }
|
191
|
+
[last_cell, next_cell_overlap] = last_visible_cell(self);
|
192
|
+
scroll_delta = (next_cell_overlap ? -next_cell_overlap : -last_cell.offsetWidth);
|
193
|
+
|
194
|
+
self.scroller.scrollLeft += scroll_delta;
|
195
|
+
if(!self.scroller.scrollLeft) { self.scroller.classList.remove(states.scroller.scrolled); }
|
196
|
+
update_actions(self);
|
197
|
+
};
|
198
|
+
|
199
|
+
//*
|
200
|
+
// Handles a keypress while focused on the table. Only left/ right/ up/ down
|
201
|
+
// keypresses are handled here: left and down will shift the table left, while
|
202
|
+
// right and up will shift the table right.
|
203
|
+
//
|
204
|
+
// @param {Object} event - The original `keypress` event.
|
205
|
+
// @param {Object} self - The internal details of a `Table`.
|
206
|
+
// @private
|
207
|
+
|
208
|
+
handle_keypress = (event, self) => {
|
209
|
+
switch(event.which) {
|
210
|
+
case Keycodes.RIGHT:
|
211
|
+
event.preventDefault();
|
212
|
+
shift_table_right(self);
|
213
|
+
break;
|
214
|
+
case Keycodes.LEFT:
|
215
|
+
event.preventDefault();
|
216
|
+
shift_table_left(self);
|
217
|
+
break;
|
218
|
+
}
|
219
|
+
};
|
220
|
+
|
221
|
+
//*
|
222
|
+
// Handles scrolling on the table by updating the classes on the scroller/
|
223
|
+
// action buttons to reflect the current scroll position.
|
224
|
+
//
|
225
|
+
// @param {Object} event - The original `scroll` event.
|
226
|
+
// @param {Object} self - The internal details of a `Table`.
|
227
|
+
// @private
|
228
|
+
|
229
|
+
handle_scroll = (event, self) => {
|
230
|
+
var scroller;
|
231
|
+
|
232
|
+
if(!self.overflowing) { return; }
|
233
|
+
|
234
|
+
scroller = self.scroller;
|
235
|
+
if(scroller.scrollLeft > 0) {
|
236
|
+
scroller.classList.add(states.scroller.scrolled);
|
237
|
+
} else {
|
238
|
+
scroller.classList.remove(states.scroller.scrolled);
|
239
|
+
}
|
240
|
+
|
241
|
+
update_actions(self);
|
242
|
+
event.stopPropagation();
|
243
|
+
};
|
244
|
+
|
245
|
+
//*
|
246
|
+
// Hooks up the event handlers for table actions, stores the actions on
|
247
|
+
// `self.shifters` for easier access later, and performes the initial updates
|
248
|
+
// to make the state of the actions match the table itself.
|
249
|
+
//
|
250
|
+
// @param {Object} self - The internal details of a `Table`.
|
251
|
+
// @private
|
252
|
+
|
253
|
+
initialize_table_actions = (self) => {
|
254
|
+
var action;
|
255
|
+
|
256
|
+
self.shifters = {};
|
257
|
+
for(action of Array.from(self.container.querySelectorAll(`.${classes.actions} [${attrs.action}]`))) {
|
258
|
+
self.shifters[action.getAttribute(attrs.action).replace("shift-", "")] = action;
|
259
|
+
}
|
260
|
+
|
261
|
+
update_actions(self);
|
262
|
+
|
263
|
+
$(self.container).on("click", `.${classes.actions}`, (event) => {
|
264
|
+
switch(event.target.getAttribute(attrs.action)) {
|
265
|
+
case actions.shift_right:
|
266
|
+
shift_table_right(self);
|
267
|
+
break;
|
268
|
+
case actions.shift_left:
|
269
|
+
shift_table_left(self);
|
270
|
+
break;
|
271
|
+
}
|
272
|
+
});
|
273
|
+
};
|
274
|
+
|
275
|
+
//*
|
276
|
+
// Updates the table actions by disabling actions that can't be performed given
|
277
|
+
// the state of the table (for example, a left shifter when the table is fully
|
278
|
+
// scrolled to the left).
|
279
|
+
//
|
280
|
+
// @param {Object} self - The internal details of a `Table`.
|
281
|
+
// @private
|
282
|
+
|
283
|
+
update_actions = (() => {
|
284
|
+
var disable, enable;
|
285
|
+
|
286
|
+
disable = (shifter) => {
|
287
|
+
shifter.disabled = true;
|
288
|
+
shifter.classList.add(`${shifter.className.split(" ")[0]}--is-disabled`);
|
289
|
+
};
|
290
|
+
|
291
|
+
enable = (shifter) => {
|
292
|
+
shifter.disabled = false;
|
293
|
+
shifter.classList.remove(`${shifter.className.split(" ")[0]}--is-disabled`);
|
294
|
+
};
|
295
|
+
|
296
|
+
return (self) => {
|
297
|
+
var shifters = self.shifters,
|
298
|
+
scroll = self.scroller.scrollLeft;
|
299
|
+
|
300
|
+
if(!scroll) {
|
301
|
+
disable(shifters.left);
|
302
|
+
} else {
|
303
|
+
enable(shifters.left);
|
304
|
+
}
|
305
|
+
|
306
|
+
if((scroll + self.scroller.offsetWidth + 1) >= self.scroller.scrollWidth) {
|
307
|
+
disable(shifters.right);
|
308
|
+
} else {
|
309
|
+
enable(shifters.right);
|
310
|
+
}
|
311
|
+
};
|
312
|
+
})();
|
313
|
+
|
314
|
+
//*
|
315
|
+
// A factory for producing `Table` objects.
|
316
|
+
//
|
317
|
+
// @param {HTMLElement} root - The root (`.table`) node of the table. Note that
|
318
|
+
// this is not the container or scroller, but the
|
319
|
+
// actual `table` element itself.
|
320
|
+
//
|
321
|
+
// @factory
|
322
|
+
|
323
|
+
Table = (root) => {
|
324
|
+
var $root, self;
|
325
|
+
|
326
|
+
$root = $(root);
|
327
|
+
self = {
|
328
|
+
root,
|
329
|
+
scroller: $root.closest(`.${classes.scroller}`)[0],
|
330
|
+
container: $root.closest(`.${classes.container}`)[0],
|
331
|
+
overflowing: false,
|
332
|
+
header_cells: Array.from(root.querySelectorAll(`.${classes.header} .${classes.cell}`))
|
333
|
+
};
|
334
|
+
|
335
|
+
root.setAttribute("tabindex", "-1");
|
336
|
+
cache_preferred_widths(self);
|
337
|
+
check_for_overflow(self);
|
338
|
+
initialize_table_actions(self);
|
339
|
+
|
340
|
+
$(window).on("resize", () => {
|
341
|
+
check_for_overflow(self);
|
342
|
+
update_actions(self);
|
343
|
+
});
|
344
|
+
|
345
|
+
root.addEventListener("keydown", (event) => { handle_keypress(event, self); });
|
346
|
+
self.scroller.addEventListener("scroll", (event) => { handle_scroll(event, self); });
|
347
|
+
};
|
348
|
+
|
349
|
+
Table.init = () => {
|
350
|
+
Builder.build(Table, { name: classes.root });
|
351
|
+
};
|