vhx-quartz 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ // Example Search Input Component
2
+
3
+ m.component(vhxm.components.shared.search_input.ui.container, {
4
+ config: function(el) {
5
+ // mithril config for post render actions
6
+ },
7
+ search: function(query, callback) {
8
+ // method for search ajax request
9
+ // passes a query (the search term)
10
+ // and callback param
11
+ },
12
+ callback: function(data) {
13
+ // callback fires when called
14
+ // via the callback param above
15
+ // passes back data from search request
16
+ },
17
+ placeholder: 'Search',
18
+ oninput: function() {
19
+ // input event handler
20
+ }
21
+ });
22
+ vhxm.components.shared.search_input.controller = function(opts) {
23
+ let self = this;
24
+
25
+ self.timeout = null;
26
+
27
+ self.debounceSearch = function(event) {
28
+ if (self.timeout) {
29
+ clearTimeout(self.timeout);
30
+ }
31
+
32
+ self.timeout = setTimeout(function() {
33
+ self.fetchResults(event.target.value);
34
+ self.timeout = null;
35
+ }, 300);
36
+ };
37
+
38
+ self.handleInput = function(event) {
39
+ self.debounceSearch(event);
40
+ };
41
+
42
+ self.fetchResults = function(query) {
43
+ opts.search(query, function(data) {
44
+ opts.callback(data);
45
+ });
46
+ };
47
+ };
48
+
49
+ vhxm.components.shared.search_input.ui.container = {
50
+ controller: function(opts) {
51
+ return new vhxm.components.shared.search_input.controller(opts);
52
+ },
53
+ view: function(ctrl, opts) {
54
+ return m('input.c-select--search.padding-right-large', {
55
+ config: opts.config ? opts.config : '',
56
+ type: 'text',
57
+ placeholder: opts.placeholder ? opts.placeholder : 'Search',
58
+ oninput: function(event) {
59
+ if (opts.oninput) {
60
+ opts.oninput(event);
61
+ }
62
+ ctrl.handleInput(event);
63
+ }
64
+ });
65
+ }
66
+ };
@@ -0,0 +1,263 @@
1
+ // Example Select Component
2
+
3
+ m.component(vhxm.components.shared.select.ui.container, {
4
+ search: mySearch(query, callback),
5
+ selected: {
6
+ value: null,
7
+ label: 'Nothing Selected'
8
+ },
9
+ items: vhxm.models.section.items,
10
+ value_prop: 'id',
11
+ label_prop: 'title',
12
+ descriptor_prop: 'details',
13
+ name: 'selected_id',
14
+ callback: function(obj) {
15
+ vhxm.models.section.chosen_item = { id: obj.value };
16
+ }
17
+ });
18
+
19
+
20
+
21
+ vhxm.components.shared.select.controller = function(opts) {
22
+ let self = this;
23
+
24
+ self.init = function() {
25
+ self.state = new vhxm.components.shared.select.state();
26
+ self.model = new vhxm.components.shared.select.model();
27
+
28
+ self.model.items = opts.items;
29
+ self.state.selected(opts.selected);
30
+
31
+ $(document).on('click', function(event) {
32
+ let is_dropdown = $(event.target).closest('.c-select--container').length;
33
+
34
+ if (!is_dropdown && self.state.isDropdownOpen()) {
35
+ m.startComputation();
36
+ self.state.isDropdownOpen(false);
37
+ m.endComputation();
38
+ }
39
+ });
40
+ };
41
+
42
+ self.selectedLabel = function() {
43
+ let is_default = true;
44
+
45
+ self.model.items().map(function(item) {
46
+ if (self.state.selected().value === item[opts.value_prop]) {
47
+ self.state.selected({
48
+ value: item[opts.value_prop],
49
+ label: item[opts.label_prop]
50
+ });
51
+ is_default = false;
52
+ }
53
+ });
54
+
55
+ if (is_default) {
56
+ self.state.selected(opts.selected);
57
+ }
58
+
59
+ return self.state.selected().label;
60
+ };
61
+
62
+
63
+ self.handleKeydown = function(e) {
64
+ let container = $(e.target).closest('.c-select--container').find('.c-select--options');
65
+
66
+ // Down Arrow
67
+ if (e.keyCode === 40) {
68
+ self.setHighlightedState('down', container);
69
+ e.preventDefault();
70
+ }
71
+ // Up Arrow
72
+ else if (e.keyCode === 38) {
73
+ self.setHighlightedState('up', container);
74
+ e.preventDefault();
75
+ }
76
+ // Enter/Return
77
+ else if (e.keyCode === 13 && self.state.isDropdownOpen()) {
78
+ self.state.selected({
79
+ value: self.model.items()[self.state.highlightIndex()][opts.value_prop],
80
+ label: self.model.items()[self.state.highlightIndex()][opts.label_prop]
81
+ });
82
+
83
+ self.state.isDropdownOpen(false);
84
+ e.preventDefault();
85
+ }
86
+ };
87
+
88
+ self.handleClick = function(event) {
89
+ event.preventDefault();
90
+ let container = $(event.target).closest('.c-select--container').find('.c-select--options');
91
+
92
+ self.state.isDropdownOpen(!self.state.isDropdownOpen());
93
+ self.state.highlightIndex(-1);
94
+
95
+ self.scrollOptionsList(container);
96
+ };
97
+
98
+ self.handleInput = function() {
99
+ self.state.isLoadingResults(true);
100
+ self.state.highlightIndex(0);
101
+ };
102
+
103
+ self.searchCallback = function(data) {
104
+ self.model.items(data);
105
+ self.state.isLoadingResults(false);
106
+ };
107
+
108
+ self.setHighlightedState = function(direction, container) {
109
+ if (direction === 'down') {
110
+ self.state.highlightIndex(self.state.highlightIndex() + 1);
111
+ if (self.state.highlightIndex() < self.model.items().length) {
112
+ self.state.scrollIndex(self.state.scrollIndex() + 1);
113
+ }
114
+ else {
115
+ self.state.highlightIndex(self.model.items().length - 1);
116
+ }
117
+ }
118
+ else if (direction === 'up') {
119
+ self.state.highlightIndex(self.state.highlightIndex() - 1);
120
+ if (self.state.highlightIndex() > 0) {
121
+ self.state.scrollIndex(self.state.scrollIndex() - 1);
122
+ }
123
+ else {
124
+ self.state.highlightIndex(0);
125
+ }
126
+ }
127
+ self.scrollOptionsList(container);
128
+ };
129
+
130
+ self.scrollOptionsList = function(container) {
131
+ if (container.length) {
132
+ container.eq(0).scrollTop(self.state.optionHeight() * self.state.highlightIndex());
133
+ }
134
+ };
135
+
136
+ if (opts.init) {
137
+ self.init();
138
+ }
139
+ };
140
+
141
+ vhxm.components.shared.select.model = function() {
142
+ this.items = m.prop(null);
143
+ };
144
+
145
+ vhxm.components.shared.select.state = function() {
146
+ this.selected = m.prop({});
147
+ this.highlighted = m.prop({});
148
+ this.isDropdownOpen = m.prop(false);
149
+ this.highlightIndex = m.prop(null);
150
+ this.scrollIndex = m.prop(0);
151
+ this.optionHeight = m.prop(0);
152
+ this.optionsHeight = m.prop(0);
153
+ this.isLoadingResults = m.prop(false);
154
+ };
155
+
156
+ vhxm.components.shared.select.ui.container = {
157
+ controller: function(opts) {
158
+ opts.init = true;
159
+ return new vhxm.components.shared.select.controller(opts);
160
+ },
161
+ view: function(ctrl, opts) {
162
+ return m('.c-select--container.form' + (opts.search ? '.has-search' : '') + (opts.inline ? '.inline' : ''), {
163
+ onkeydown: ctrl.handleKeydown
164
+ }, [
165
+ m('a.c-select--trigger.btn-dropdown-' + (opts.color ? opts.color : 'gray') + '.btn--fill' + (ctrl.state.isDropdownOpen() ? '.is-active' : ''), {
166
+ href: '#',
167
+ onclick: ctrl.handleClick
168
+ }, ctrl.selectedLabel()),
169
+ m('.c-select--dropdown' + (ctrl.state.isDropdownOpen() ? '.is-open' : ''), [
170
+ opts.search ?
171
+ // if search is enabled
172
+ m('.c-select--input-container.padding-medium', [
173
+ m.component(vhxm.components.shared.search_input.ui.container, {
174
+ config: function(el) {
175
+ if (ctrl.state.isDropdownOpen()) {
176
+ setTimeout(function() {
177
+ el.focus();
178
+ }, 10);
179
+ }
180
+ },
181
+ callback: ctrl.searchCallback,
182
+ search: opts.search,
183
+ placeholder: 'Search',
184
+ oninput: ctrl.handleInput
185
+ })
186
+ ]) : '',
187
+ m.component(vhxm.components.shared.select.ui.list.container, opts, ctrl),
188
+ m('input', {
189
+ type: 'hidden',
190
+ name: opts.name,
191
+ value: ctrl.state.selected().value
192
+ })
193
+ ])
194
+ ]);
195
+ }
196
+ };
197
+
198
+ vhxm.components.shared.select.ui.list.controller = function(opts, parent) {
199
+ let self = this;
200
+
201
+ self.parent = new vhxm.components.shared.select.controller(opts);
202
+ self.state = parent.state;
203
+ self.model = parent.model;
204
+
205
+ self.hasItems = function() {
206
+ return self.model.items() && self.model.items().length > 1;
207
+ };
208
+
209
+ self.handleItemClick = function(event, item) {
210
+ self.state.selected({
211
+ value: item[opts.value_prop],
212
+ label: item[opts.label_prop]
213
+ });
214
+ self.state.isDropdownOpen(false);
215
+ self.state.highlightIndex(-1);
216
+ if (opts.callback) {
217
+ opts.callback(self.state.selected());
218
+ }
219
+ self.parent.scrollOptionsList(0);
220
+ };
221
+
222
+ };
223
+
224
+ /* ................................................
225
+ Select List Component
226
+ .................................................*/
227
+ vhxm.components.shared.select.ui.list.container = {
228
+ controller: function(opts, parent) {
229
+ return new vhxm.components.shared.select.ui.list.controller(opts, parent);
230
+ },
231
+ view: function(ctrl, opts) {
232
+ return m('ul.c-select--options.margin-left-reset' + (ctrl.state.isLoadingResults() ? '.is-loading.padding-bottom-medium' : ''), {
233
+ config: function(el) {
234
+ ctrl.state.optionsHeight($(el).outerHeight());
235
+ }
236
+ }, [
237
+ ctrl.hasItems() ?
238
+ ctrl.model.items().map(function(item, index) {
239
+ return m('li.c-select--option.padding-horizontal-large.padding-vertical-small' + (index === ctrl.state.highlightIndex() ? '.is-selected' : ''), {
240
+ config: function(el) {
241
+ ctrl.state.optionHeight($(el).outerHeight());
242
+ },
243
+ onmouseover: function() {
244
+ ctrl.state.highlightIndex(index);
245
+ },
246
+ onclick: function(event) {
247
+ ctrl.handleItemClick(event, item);
248
+ }
249
+ }, [
250
+ m('span.c-select--item-label', item[opts.label_prop]), item[opts.descriptor_prop] ? m('span.right.text.primary', item[opts.descriptor_prop]) : '' ]);
251
+ })
252
+ : m.component(vhxm.components.shared.select.ui.list.empty, opts)
253
+ ]);
254
+ }
255
+ };
256
+
257
+ /* List Empty
258
+ .................................................*/
259
+ vhxm.components.shared.select.ui.list.empty = {
260
+ view: function() {
261
+ return m('li.c-select--option.padding-horizontal-large.padding-top-small.padding-bottom-medium.text.primary', 'No results');
262
+ }
263
+ };
@@ -0,0 +1,67 @@
1
+ /* .....................................
2
+ Fonts
3
+ ..................................... */
4
+ /* .....................................
5
+ Sets
6
+ ..................................... */
7
+ /* .....................................
8
+ Media Query Ranges
9
+ ..................................... */
10
+ /* .....................................
11
+ Colors - Grays
12
+ ..................................... */
13
+ /* .....................................
14
+ Colors - Teals
15
+ ..................................... */
16
+ /* .....................................
17
+ Colors - Red
18
+ ..................................... */
19
+ /* .....................................
20
+ Colors - Navy
21
+ ..................................... */
22
+ /* .....................................
23
+ Colors - Brand Palette
24
+ ..................................... */
25
+ /* .....................................
26
+ Colors - External Palette
27
+ ..................................... */
28
+ /* helper function for margin and padding
29
+ ......................................*/
30
+ .c-autosuggest--container {
31
+ position: relative; }
32
+
33
+ .c-autosuggest--list {
34
+ width: 100%;
35
+ position: absolute;
36
+ background-color: #fff;
37
+ background: #ffffff;
38
+ z-index: 2147483600;
39
+ border: 1px solid #D7DDE1;
40
+ border-top: none;
41
+ display: none; }
42
+ .c-autosuggest--list.is-open {
43
+ display: block; }
44
+
45
+ .c-autosuggest--input-container {
46
+ width: 100%;
47
+ background: #ffffff; }
48
+ .c-autosuggest--input-container input {
49
+ border-radius: 3px 3px 0px 0 !important; }
50
+
51
+ .c-autosuggest--options {
52
+ overflow-y: auto;
53
+ margin-bottom: 0;
54
+ max-height: 210px; }
55
+ .c-autosuggest--options.is-loading {
56
+ background-position: center center;
57
+ background-size: 40px;
58
+ background-repeat: no-repeat;
59
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%0D%0A%20%20viewBox%3D%220%200%2040%2040%22%20xml%3Aspace%3D%22preserve%22%3E%0D%0A%3Cpath%20opacity%3D%220.2%22%20fill%3D%22%237a878e%22%20d%3D%22M20.201%2C5.169c-8.254%2C0-14.946%2C6.692-14.946%2C14.946c0%2C8.255%2C6.692%2C14.946%2C14.946%2C14.946%0D%0A%20%20s14.946-6.691%2C14.946-14.946C35.146%2C11.861%2C28.455%2C5.169%2C20.201%2C5.169z%20M20.201%2C31.749c-6.425%2C0-11.634-5.208-11.634-11.634%0D%0A%20%20c0-6.425%2C5.209-11.634%2C11.634-11.634c6.425%2C0%2C11.633%2C5.209%2C11.633%2C11.634C31.834%2C26.541%2C26.626%2C31.749%2C20.201%2C31.749z%22%2F%3E%0D%0A%3Cpath%20fill%3D%22%237a878e%22%20d%3D%22M26.013%2C10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0%0D%0A%20%20C22.32%2C8.481%2C24.301%2C9.057%2C26.013%2C10.047z%22%3E%0D%0A%20%20%3CanimateTransform%20attributeType%3D%22xml%22%0D%0A%20%20%20%20attributeName%3D%22transform%22%0D%0A%20%20%20%20type%3D%22rotate%22%0D%0A%20%20%20%20from%3D%220%2020%2020%22%0D%0A%20%20%20%20to%3D%22360%2020%2020%22%0D%0A%20%20%20%20dur%3D%220.5s%22%0D%0A%20%20%20%20repeatCount%3D%22indefinite%22%2F%3E%0D%0A%20%20%3C%2Fpath%3E%0D%0A%3C%2Fsvg%3E"); }
60
+ .c-autosuggest--options.is-loading li {
61
+ opacity: 0; }
62
+
63
+ .c-autosuggest--option {
64
+ color: #233741; }
65
+ .c-autosuggest--option.is-selected {
66
+ cursor: pointer;
67
+ background-color: #F0F2F4; }