ldbws 1.0.3 → 1.0.4

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/Gemfile.lock +147 -49
  4. data/LICENSE +1 -1
  5. data/README.md +2 -2
  6. data/doc/LICENSE.html +403 -47
  7. data/doc/Ldbws/Request/GetDeparturesBoard.html +487 -54
  8. data/doc/Ldbws/Request/GetDeparturesBoardWithDetails.html +487 -54
  9. data/doc/Ldbws/Request/GetServiceDetails.html +484 -51
  10. data/doc/Ldbws/Request/GetStationBoard.html +489 -56
  11. data/doc/Ldbws/Request/GetStationBoardWithDetails.html +489 -56
  12. data/doc/Ldbws/Request/ParamValidationError.html +538 -69
  13. data/doc/Ldbws/Request.html +470 -47
  14. data/doc/Ldbws/RequestError.html +535 -72
  15. data/doc/Ldbws/ResponseParsingError.html +475 -49
  16. data/doc/Ldbws/ResponseTypes/BaseStationBoard.html +565 -56
  17. data/doc/Ldbws/ResponseTypes/CallingPoint.html +498 -65
  18. data/doc/Ldbws/ResponseTypes/Coach.html +487 -54
  19. data/doc/Ldbws/ResponseTypes/DepartureItem.html +485 -52
  20. data/doc/Ldbws/ResponseTypes/DepartureItemWithDetails.html +485 -52
  21. data/doc/Ldbws/ResponseTypes/DeparturesBoard.html +484 -51
  22. data/doc/Ldbws/ResponseTypes/DeparturesBoardWithDetails.html +484 -51
  23. data/doc/Ldbws/ResponseTypes/Formation.html +485 -52
  24. data/doc/Ldbws/ResponseTypes/LoadingCategory.html +486 -53
  25. data/doc/Ldbws/ResponseTypes/Location.html +486 -53
  26. data/doc/Ldbws/ResponseTypes/ServiceDetails.html +510 -77
  27. data/doc/Ldbws/ResponseTypes/ServiceItem.html +503 -70
  28. data/doc/Ldbws/ResponseTypes/ServiceItemWithCallingPoints.html +485 -52
  29. data/doc/Ldbws/ResponseTypes/StationBoard.html +486 -53
  30. data/doc/Ldbws/ResponseTypes/StationBoardWithDetails.html +486 -53
  31. data/doc/Ldbws/ResponseTypes/ToiletAvailability.html +485 -52
  32. data/doc/Ldbws/ResponseTypes.html +470 -47
  33. data/doc/Ldbws/Service.html +1083 -245
  34. data/doc/Ldbws.html +520 -73
  35. data/doc/created.rid +19 -20
  36. data/doc/css/rdoc.css +1926 -378
  37. data/doc/index.html +434 -104
  38. data/doc/js/aliki.js +489 -0
  39. data/doc/js/bash_highlighter.js +167 -0
  40. data/doc/js/c_highlighter.js +299 -0
  41. data/doc/js/search_controller.js +129 -0
  42. data/doc/js/search_data.js +1 -0
  43. data/doc/js/search_navigation.js +105 -0
  44. data/doc/js/search_ranker.js +239 -0
  45. data/doc/js/theme-toggle.js +112 -0
  46. data/ldbws.gemspec +7 -6
  47. data/lib/ldbws/request/base.rb +0 -3
  48. data/lib/ldbws/request/get_departures_board.rb +3 -1
  49. data/lib/ldbws/request/get_service_details.rb +2 -0
  50. data/lib/ldbws/request/get_station_board.rb +12 -2
  51. data/lib/ldbws/response_types/calling_point.rb +2 -2
  52. data/lib/ldbws/response_types/station_board.rb +6 -0
  53. data/lib/ldbws/version.rb +1 -1
  54. data/spec/helpers/request_helper.rb +27 -0
  55. data/spec/request/get_departures_board_spec.rb +55 -0
  56. data/spec/request/get_service_details_spec.rb +16 -0
  57. data/spec/request/get_station_board_spec.rb +73 -0
  58. metadata +29 -21
  59. data/.envrc +0 -1
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Client-side C syntax highlighter for RDoc
3
+ */
4
+
5
+ (function() {
6
+ 'use strict';
7
+
8
+ // C control flow and storage class keywords
9
+ const C_KEYWORDS = new Set([
10
+ 'auto', 'break', 'case', 'continue', 'default', 'do', 'else', 'extern',
11
+ 'for', 'goto', 'if', 'inline', 'register', 'return', 'sizeof', 'static',
12
+ 'switch', 'while',
13
+ '_Alignas', '_Alignof', '_Generic', '_Noreturn', '_Static_assert', '_Thread_local'
14
+ ]);
15
+
16
+ // C type keywords and type qualifiers
17
+ const C_TYPE_KEYWORDS = new Set([
18
+ 'bool', 'char', 'const', 'double', 'enum', 'float', 'int', 'long',
19
+ 'restrict', 'short', 'signed', 'struct', 'typedef', 'union', 'unsigned',
20
+ 'void', 'volatile', '_Atomic', '_Bool', '_Complex', '_Imaginary'
21
+ ]);
22
+
23
+ // Library-defined types (typedef'd in headers, not language keywords)
24
+ // Includes: Ruby C API types (VALUE, ID), POSIX types (size_t, ssize_t),
25
+ // fixed-width integer types (uint32_t, int64_t), and standard I/O types (FILE)
26
+ const C_TYPES = new Set([
27
+ 'VALUE', 'ID', 'size_t', 'ssize_t', 'ptrdiff_t', 'uintptr_t', 'intptr_t',
28
+ 'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t',
29
+ 'int8_t', 'int16_t', 'int32_t', 'int64_t',
30
+ 'FILE', 'DIR', 'va_list'
31
+ ]);
32
+
33
+ // Common Ruby VALUE macros and boolean literals
34
+ const RUBY_MACROS = new Set([
35
+ 'Qtrue', 'Qfalse', 'Qnil', 'Qundef', 'NULL', 'TRUE', 'FALSE', 'true', 'false'
36
+ ]);
37
+
38
+ const OPERATORS = new Set([
39
+ '==', '!=', '<=', '>=', '&&', '||', '<<', '>>', '++', '--',
40
+ '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '->',
41
+ '+', '-', '*', '/', '%', '<', '>', '=', '!', '&', '|', '^', '~'
42
+ ]);
43
+
44
+ // Single character that can start an operator
45
+ const OPERATOR_CHARS = new Set('+-*/%<>=!&|^~');
46
+
47
+ function isMacro(word) {
48
+ return RUBY_MACROS.has(word) || /^[A-Z][A-Z0-9_]*$/.test(word);
49
+ }
50
+
51
+ function isType(word) {
52
+ return C_TYPE_KEYWORDS.has(word) || C_TYPES.has(word) || /_t$/.test(word);
53
+ }
54
+
55
+ /**
56
+ * Escape HTML special characters
57
+ */
58
+ function escapeHtml(text) {
59
+ return text
60
+ .replace(/&/g, '&amp;')
61
+ .replace(/</g, '&lt;')
62
+ .replace(/>/g, '&gt;')
63
+ .replace(/"/g, '&quot;')
64
+ .replace(/'/g, '&#39;');
65
+ }
66
+
67
+ /**
68
+ * Check if position is at line start (only whitespace before it)
69
+ */
70
+ function isLineStart(code, pos) {
71
+ if (pos === 0) return true;
72
+ for (let i = pos - 1; i >= 0; i--) {
73
+ const ch = code[i];
74
+ if (ch === '\n') return true;
75
+ if (ch !== ' ' && ch !== '\t') return false;
76
+ }
77
+ return true;
78
+ }
79
+
80
+ /**
81
+ * Highlight C source code
82
+ */
83
+ function highlightC(code) {
84
+ const tokens = [];
85
+ let i = 0;
86
+ const len = code.length;
87
+
88
+ while (i < len) {
89
+ const char = code[i];
90
+
91
+ // Multi-line comment
92
+ if (char === '/' && code[i + 1] === '*') {
93
+ let end = code.indexOf('*/', i + 2);
94
+ end = (end === -1) ? len : end + 2;
95
+ const comment = code.substring(i, end);
96
+ tokens.push('<span class="c-comment">', escapeHtml(comment), '</span>');
97
+ i = end;
98
+ continue;
99
+ }
100
+
101
+ // Single-line comment
102
+ if (char === '/' && code[i + 1] === '/') {
103
+ const end = code.indexOf('\n', i);
104
+ const commentEnd = (end === -1) ? len : end;
105
+ const comment = code.substring(i, commentEnd);
106
+ tokens.push('<span class="c-comment">', escapeHtml(comment), '</span>');
107
+ i = commentEnd;
108
+ continue;
109
+ }
110
+
111
+ // Preprocessor directive (must be at line start)
112
+ if (char === '#' && isLineStart(code, i)) {
113
+ let end = i + 1;
114
+ while (end < len && code[end] !== '\n') {
115
+ if (code[end] === '\\' && end + 1 < len && code[end + 1] === '\n') {
116
+ end += 2; // Handle line continuation
117
+ } else {
118
+ end++;
119
+ }
120
+ }
121
+ const preprocessor = code.substring(i, end);
122
+ tokens.push('<span class="c-preprocessor">', escapeHtml(preprocessor), '</span>');
123
+ i = end;
124
+ continue;
125
+ }
126
+
127
+ // String literal
128
+ if (char === '"') {
129
+ let end = i + 1;
130
+ while (end < len && code[end] !== '"') {
131
+ if (code[end] === '\\' && end + 1 < len) {
132
+ end += 2; // Skip escaped character
133
+ } else {
134
+ end++;
135
+ }
136
+ }
137
+ if (end < len) end++; // Include closing quote
138
+ const string = code.substring(i, end);
139
+ tokens.push('<span class="c-string">', escapeHtml(string), '</span>');
140
+ i = end;
141
+ continue;
142
+ }
143
+
144
+ // Character literal
145
+ if (char === "'") {
146
+ let end = i + 1;
147
+ // Handle escape sequences like '\n', '\\', '\''
148
+ if (end < len && code[end] === '\\' && end + 1 < len) {
149
+ end += 2; // Skip backslash and escaped char
150
+ } else if (end < len) {
151
+ end++; // Single character
152
+ }
153
+ if (end < len && code[end] === "'") end++; // Closing quote
154
+ const charLit = code.substring(i, end);
155
+ tokens.push('<span class="c-value">', escapeHtml(charLit), '</span>');
156
+ i = end;
157
+ continue;
158
+ }
159
+
160
+ // Number (integer or float)
161
+ if (char >= '0' && char <= '9') {
162
+ let end = i;
163
+
164
+ // Hexadecimal
165
+ if (char === '0' && (code[i + 1] === 'x' || code[i + 1] === 'X')) {
166
+ end = i + 2;
167
+ while (end < len) {
168
+ const ch = code[end];
169
+ if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
170
+ end++;
171
+ } else {
172
+ break;
173
+ }
174
+ }
175
+ }
176
+ // Octal
177
+ else if (char === '0' && code[i + 1] >= '0' && code[i + 1] <= '7') {
178
+ end = i + 1;
179
+ while (end < len && code[end] >= '0' && code[end] <= '7') end++;
180
+ }
181
+ // Decimal/Float
182
+ else {
183
+ while (end < len) {
184
+ const ch = code[end];
185
+ if ((ch >= '0' && ch <= '9') || ch === '.') {
186
+ end++;
187
+ } else {
188
+ break;
189
+ }
190
+ }
191
+ // Scientific notation
192
+ if (end < len && (code[end] === 'e' || code[end] === 'E')) {
193
+ end++;
194
+ if (end < len && (code[end] === '+' || code[end] === '-')) end++;
195
+ while (end < len && code[end] >= '0' && code[end] <= '9') end++;
196
+ }
197
+ }
198
+
199
+ // Suffix (u, l, f, etc.)
200
+ while (end < len) {
201
+ const ch = code[end];
202
+ if (ch === 'u' || ch === 'U' || ch === 'l' || ch === 'L' || ch === 'f' || ch === 'F') {
203
+ end++;
204
+ } else {
205
+ break;
206
+ }
207
+ }
208
+
209
+ const number = code.substring(i, end);
210
+ tokens.push('<span class="c-value">', escapeHtml(number), '</span>');
211
+ i = end;
212
+ continue;
213
+ }
214
+
215
+ // Identifier or keyword
216
+ if ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || char === '_') {
217
+ let end = i + 1;
218
+ while (end < len) {
219
+ const ch = code[end];
220
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
221
+ (ch >= '0' && ch <= '9') || ch === '_') {
222
+ end++;
223
+ } else {
224
+ break;
225
+ }
226
+ }
227
+ const word = code.substring(i, end);
228
+
229
+ if (C_KEYWORDS.has(word)) {
230
+ tokens.push('<span class="c-keyword">', escapeHtml(word), '</span>');
231
+ } else if (isType(word)) {
232
+ // Check types before macros (VALUE, ID are types, not macros)
233
+ tokens.push('<span class="c-type">', escapeHtml(word), '</span>');
234
+ } else if (isMacro(word)) {
235
+ tokens.push('<span class="c-macro">', escapeHtml(word), '</span>');
236
+ } else {
237
+ // Check if followed by '(' -> function name
238
+ let nextCharIdx = end;
239
+ while (nextCharIdx < len && (code[nextCharIdx] === ' ' || code[nextCharIdx] === '\t')) {
240
+ nextCharIdx++;
241
+ }
242
+ if (nextCharIdx < len && code[nextCharIdx] === '(') {
243
+ tokens.push('<span class="c-function">', escapeHtml(word), '</span>');
244
+ } else {
245
+ tokens.push('<span class="c-identifier">', escapeHtml(word), '</span>');
246
+ }
247
+ }
248
+ i = end;
249
+ continue;
250
+ }
251
+
252
+ // Operators
253
+ if (OPERATOR_CHARS.has(char)) {
254
+ let op = char;
255
+ // Check for two-character operators
256
+ if (i + 1 < len) {
257
+ const twoChar = char + code[i + 1];
258
+ if (OPERATORS.has(twoChar)) {
259
+ op = twoChar;
260
+ }
261
+ }
262
+ tokens.push('<span class="c-operator">', escapeHtml(op), '</span>');
263
+ i += op.length;
264
+ continue;
265
+ }
266
+
267
+ // Everything else (punctuation, whitespace)
268
+ tokens.push(escapeHtml(char));
269
+ i++;
270
+ }
271
+
272
+ return tokens.join('');
273
+ }
274
+
275
+ /**
276
+ * Initialize C syntax highlighting on page load
277
+ */
278
+ function initHighlighting() {
279
+ const codeBlocks = document.querySelectorAll('pre.c');
280
+
281
+ codeBlocks.forEach(block => {
282
+ if (block.getAttribute('data-highlighted') === 'true') {
283
+ return;
284
+ }
285
+
286
+ const code = block.textContent;
287
+ const highlighted = highlightC(code);
288
+
289
+ block.innerHTML = highlighted;
290
+ block.setAttribute('data-highlighted', 'true');
291
+ });
292
+ }
293
+
294
+ if (document.readyState === 'loading') {
295
+ document.addEventListener('DOMContentLoaded', initHighlighting);
296
+ } else {
297
+ initHighlighting();
298
+ }
299
+ })();
@@ -0,0 +1,129 @@
1
+ SearchController = function(data, input, result) {
2
+ this.data = data;
3
+ this.input = input;
4
+ this.result = result;
5
+
6
+ this.current = null;
7
+ this.view = this.result.parentNode;
8
+ this.ranker = new SearchRanker(data.index);
9
+ this.init();
10
+ }
11
+
12
+ SearchController.prototype = Object.assign({}, SearchNavigation, new function() {
13
+ var suid = 1;
14
+
15
+ this.init = function() {
16
+ var _this = this;
17
+ var observer = function(e) {
18
+ switch(e.key) {
19
+ case 'ArrowUp':
20
+ case 'ArrowDown':
21
+ return;
22
+ }
23
+ _this.search(_this.input.value);
24
+ };
25
+ this.input.addEventListener('keyup', observer);
26
+ this.input.addEventListener('click', observer); // mac's clear field
27
+
28
+ this.ranker.ready(function(results, isLast) {
29
+ _this.addResults(results, isLast);
30
+ })
31
+
32
+ this.initNavigation();
33
+ this.setNavigationActive(false);
34
+ }
35
+
36
+ this.search = function(value, selectFirstMatch) {
37
+ this.selectFirstMatch = selectFirstMatch;
38
+
39
+ value = value.trim();
40
+ if (value) {
41
+ this.setNavigationActive(true);
42
+ } else {
43
+ this.setNavigationActive(false);
44
+ }
45
+
46
+ if (value == '') {
47
+ this.lastQuery = value;
48
+ this.result.innerHTML = '';
49
+ this.result.setAttribute('aria-expanded', 'false');
50
+ this.setNavigationActive(false);
51
+ } else if (value != this.lastQuery) {
52
+ this.lastQuery = value;
53
+ this.result.setAttribute('aria-busy', 'true');
54
+ this.result.setAttribute('aria-expanded', 'true');
55
+ this.firstRun = true;
56
+ this.ranker.find(value);
57
+ }
58
+ }
59
+
60
+ this.addResults = function(results, isLast) {
61
+ var target = this.result;
62
+ if (this.firstRun && (results.length > 0 || isLast)) {
63
+ this.current = null;
64
+ this.result.innerHTML = '';
65
+ }
66
+
67
+ for (var i=0, l = results.length; i < l; i++) {
68
+ var item = this.renderItem.call(this, results[i]);
69
+ item.setAttribute('id', 'search-result-' + target.childElementCount);
70
+ target.appendChild(item);
71
+ };
72
+
73
+ if (this.firstRun && results.length > 0) {
74
+ this.firstRun = false;
75
+ this.current = target.firstChild;
76
+ this.current.classList.add('search-selected');
77
+ }
78
+ //TODO: ECMAScript
79
+ //if (jQuery.browser.msie) this.$element[0].className += '';
80
+
81
+ if (this.selectFirstMatch && this.current) {
82
+ this.selectFirstMatch = false;
83
+ this.select(this.current);
84
+ }
85
+
86
+ if (isLast) {
87
+ this.selectFirstMatch = false;
88
+ this.result.setAttribute('aria-busy', 'false');
89
+ }
90
+ }
91
+
92
+ this.move = function(isDown) {
93
+ if (!this.current) return;
94
+ var next = isDown ? this.current.nextElementSibling : this.current.previousElementSibling;
95
+ if (next) {
96
+ this.current.classList.remove('search-selected');
97
+ next.classList.add('search-selected');
98
+ this.input.setAttribute('aria-activedescendant', next.getAttribute('id'));
99
+ this.scrollInElement(next, this.result);
100
+ this.current = next;
101
+ this.input.value = next.firstChild.firstChild.text;
102
+ this.input.select();
103
+ }
104
+ return true;
105
+ }
106
+
107
+ this.hlt = function(html) {
108
+ return this.escapeHTML(html).
109
+ replace(/\u0001/g, '<em>').
110
+ replace(/\u0002/g, '</em>');
111
+ }
112
+
113
+ this.escapeHTML = function(html) {
114
+ return html.replace(/[&<>"`']/g, function(c) {
115
+ return '&#' + c.charCodeAt(0) + ';';
116
+ });
117
+ }
118
+
119
+ this.hide = function() {
120
+ this.result.setAttribute('aria-expanded', 'false');
121
+ this.setNavigationActive(false);
122
+ }
123
+
124
+ this.show = function() {
125
+ this.result.setAttribute('aria-expanded', 'true');
126
+ this.setNavigationActive(true);
127
+ }
128
+ });
129
+
@@ -0,0 +1 @@
1
+ var search_data = {"index":[{"name":"Ldbws","full_name":"Ldbws","type":"module","path":"Ldbws.html","snippet":"<p>Provides a Ruby abstraction around the UK’s Network Rail live departure board webservice (LDBWS). See …\n"},{"name":"VERSION","full_name":"Ldbws::VERSION","type":"constant","path":"Ldbws.html","snippet":"<p>The current gem version.\n"},{"name":"Request","full_name":"Ldbws::Request","type":"module","path":"Ldbws/Request.html"},{"name":"GetDeparturesBoard","full_name":"Ldbws::Request::GetDeparturesBoard","type":"class","path":"Ldbws/Request/GetDeparturesBoard.html","snippet":"<p>Requests a departure board for a station, filtered by departures to one or many other stations. Corresponds …\n"},{"name":"GetDeparturesBoardWithDetails","full_name":"Ldbws::Request::GetDeparturesBoardWithDetails","type":"class","path":"Ldbws/Request/GetDeparturesBoardWithDetails.html","snippet":"<p>Requests a departure board for a statuion, filtered by departures to one or more other stations. This …\n"},{"name":"GetServiceDetails","full_name":"Ldbws::Request::GetServiceDetails","type":"class","path":"Ldbws/Request/GetServiceDetails.html","snippet":"<p>Returns details about a particular service. Corresponds to <code>GetServiceDetailsResponse</code> in the LDBWS schema. …\n"},{"name":"GetStationBoard","full_name":"Ldbws::Request::GetStationBoard","type":"class","path":"Ldbws/Request/GetStationBoard.html","snippet":"<p>Returns an arrival or departure board for a given station. Corresponds to <code>GetStationBoardRequest</code> in the …\n"},{"name":"GetStationBoardWithDetails","full_name":"Ldbws::Request::GetStationBoardWithDetails","type":"class","path":"Ldbws/Request/GetStationBoardWithDetails.html","snippet":"<p>Returns an arrival or departure board for a given station with full service details. Corresponds to …\n"},{"name":"ParamValidationError","full_name":"Ldbws::Request::ParamValidationError","type":"class","path":"Ldbws/Request/ParamValidationError.html","snippet":"<p>Raised when an error occurs when validating request parameters. Messages are passed through directly …\n"},{"name":"RequestError","full_name":"Ldbws::RequestError","type":"class","path":"Ldbws/RequestError.html","snippet":"<p>Raised when a request has resulted in an error that this library can make some sense of. This <em>usually</em> …\n"},{"name":"ResponseParsingError","full_name":"Ldbws::ResponseParsingError","type":"class","path":"Ldbws/ResponseParsingError.html","snippet":"<p>Raised when a response from LDBWS cannot be parsed by this library. This is unexpected, and generally …\n"},{"name":"ResponseTypes","full_name":"Ldbws::ResponseTypes","type":"module","path":"Ldbws/ResponseTypes.html"},{"name":"BaseStationBoard","full_name":"Ldbws::ResponseTypes::BaseStationBoard","type":"class","path":"Ldbws/ResponseTypes/BaseStationBoard.html","snippet":"<p>Base station board information. This does not directly correspond to a type in LDBWS.\n<p>Properties\n"},{"name":"CallingPoint","full_name":"Ldbws::ResponseTypes::CallingPoint","type":"class","path":"Ldbws/ResponseTypes/CallingPoint.html","snippet":"<p>Represents a calling point in the LDBWS.\n<p>Properties\n<p>location_name &mdash; the name of the station\n"},{"name":"Coach","full_name":"Ldbws::ResponseTypes::Coach","type":"class","path":"Ldbws/ResponseTypes/Coach.html","snippet":"<p>Information about an individual coach in the train.\n<p>Properties\n<p>number &mdash; the coach number or identifier\n"},{"name":"DepartureItem","full_name":"Ldbws::ResponseTypes::DepartureItem","type":"class","path":"Ldbws/ResponseTypes/DepartureItem.html","snippet":"<p>Represents an item on a departure board.\n<p>Properties\n<p>crs &mdash; the CRS for the item\n"},{"name":"DepartureItemWithDetails","full_name":"Ldbws::ResponseTypes::DepartureItemWithDetails","type":"class","path":"Ldbws/ResponseTypes/DepartureItemWithDetails.html","snippet":"<p>Represents an item on a departure board with additional details.\n<p>Properties\n<p>crs &mdash; the CRS for the item\n"},{"name":"DeparturesBoard","full_name":"Ldbws::ResponseTypes::DeparturesBoard","type":"class","path":"Ldbws/ResponseTypes/DeparturesBoard.html","snippet":"<p>Represents a departures board.\n<p>Properties\n<p>departures &mdash; a list of departures.\n"},{"name":"DeparturesBoardWithDetails","full_name":"Ldbws::ResponseTypes::DeparturesBoardWithDetails","type":"class","path":"Ldbws/ResponseTypes/DeparturesBoardWithDetails.html","snippet":"<p>Represents a departures board with additional details.\n<p>Properties\n<p>departures &mdash; a list of departures.\n"},{"name":"Formation","full_name":"Ldbws::ResponseTypes::Formation","type":"class","path":"Ldbws/ResponseTypes/Formation.html","snippet":"<p>Information about the formation of a train\n<p>Properties\n<p>loading_category &mdash; how heavily-loaded the train is. …\n"},{"name":"LoadingCategory","full_name":"Ldbws::ResponseTypes::LoadingCategory","type":"class","path":"Ldbws/ResponseTypes/LoadingCategory.html","snippet":"<p>The loading category of a train\n<p>Properties\n<p>code, colour, image &mdash; \n"},{"name":"Location","full_name":"Ldbws::ResponseTypes::Location","type":"class","path":"Ldbws/ResponseTypes/Location.html","snippet":"<p>Represents a location in LDBWS.\n<p>Properties\n<p>name, crs, via &mdash; \n"},{"name":"ServiceDetails","full_name":"Ldbws::ResponseTypes::ServiceDetails","type":"class","path":"Ldbws/ResponseTypes/ServiceDetails.html","snippet":"<p>Represents details about a service in LDBWS.\n<p>Properties\n"},{"name":"ServiceItem","full_name":"Ldbws::ResponseTypes::ServiceItem","type":"class","path":"Ldbws/ResponseTypes/ServiceItem.html","snippet":"<p>Represents a service item in LDBWS.\n<p>Properties\n<p>sta &mdash; the scheduled arrival time as a Time object\n"},{"name":"ServiceItemWithCallingPoints","full_name":"Ldbws::ResponseTypes::ServiceItemWithCallingPoints","type":"class","path":"Ldbws/ResponseTypes/ServiceItemWithCallingPoints.html","snippet":"<p>Represents a service item with additional details in LDBWS: extends ServiceItem.\n<p>Properties\n<p>As ServiceItem …\n"},{"name":"StationBoard","full_name":"Ldbws::ResponseTypes::StationBoard","type":"class","path":"Ldbws/ResponseTypes/StationBoard.html","snippet":"<p>Represents a station arrival/departure board in LDBWS.\n<p>Properties\n<p>As BaseStationBoard, and additionally: …\n"},{"name":"StationBoardWithDetails","full_name":"Ldbws::ResponseTypes::StationBoardWithDetails","type":"class","path":"Ldbws/ResponseTypes/StationBoardWithDetails.html","snippet":"<p>Represents a station arrival/departure board with additional details in LDBWS.\n<p>Properties\n<p>As BaseStationBoard …\n"},{"name":"ToiletAvailability","full_name":"Ldbws::ResponseTypes::ToiletAvailability","type":"class","path":"Ldbws/ResponseTypes/ToiletAvailability.html","snippet":"<p>The availability of an individual toilet on a train\n<p>Properties\n<p>type &mdash; the type of toilet\n"},{"name":"Service","full_name":"Ldbws::Service","type":"class","path":"Ldbws/Service.html","snippet":"<p>A wrapper around the National Rail Live Departure Boards Webservice (LDBWS) API.\n<p>API methods are pretty …\n"},{"name":"new","full_name":"Ldbws::Service::new","type":"class_method","path":"Ldbws/Service.html#method-c-new","snippet":"<p>Creates a service object.\n<p>Parameters\n<p>token &mdash; the API token used to connect to the service\n"},{"name":"service","full_name":"Ldbws::service","type":"class_method","path":"Ldbws.html#method-c-service","snippet":"<p>Helper method that returns an instance of [Service].\n<p>Parameters\n<p>token &mdash; the API token used to connect to …\n"},{"name":"all_services","full_name":"Ldbws::ResponseTypes::BaseStationBoard#all_services","type":"instance_method","path":"Ldbws/ResponseTypes/BaseStationBoard.html#method-i-all_services","snippet":"<p>Returns a combined list of all services (train, bus, and ferry), ordered by scheduled time of departure …\n"},{"name":"details","full_name":"Ldbws::RequestError#details","type":"instance_method","path":"Ldbws/RequestError.html#method-i-details","snippet":"<p>Returns the details of the error as a hash.\n"},{"name":"get_arr_board_with_details","full_name":"Ldbws::Service#get_arr_board_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_arr_board_with_details","snippet":"<p>Retrieves a detailed station arrival board.\n<p>Parameters are validated using GetStationBoardWithDetails …\n"},{"name":"get_arr_dep_board_with_details","full_name":"Ldbws::Service#get_arr_dep_board_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_arr_dep_board_with_details","snippet":"<p>Retrieves a detailed station arrival + departures board.\n<p>Parameters are validated using GetStationBoardWithDetails …\n"},{"name":"get_arrival_board","full_name":"Ldbws::Service#get_arrival_board","type":"instance_method","path":"Ldbws/Service.html#method-i-get_arrival_board","snippet":"<p>Retrieves a station arrival board.\n<p>Parameters are validated using GetStationBoard, returns a StationBoard …\n"},{"name":"get_arrival_board_with_details","full_name":"Ldbws::Service#get_arrival_board_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_arrival_board_with_details"},{"name":"get_arrival_departure_board","full_name":"Ldbws::Service#get_arrival_departure_board","type":"instance_method","path":"Ldbws/Service.html#method-i-get_arrival_departure_board","snippet":"<p>Retrieves a station arrival + departure board.\n<p>Parameters are validated using GetStationBoard, returns …\n"},{"name":"get_arrival_departure_board_with_details","full_name":"Ldbws::Service#get_arrival_departure_board_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_arrival_departure_board_with_details"},{"name":"get_dep_board_with_details","full_name":"Ldbws::Service#get_dep_board_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_dep_board_with_details","snippet":"<p>Retrieves a detailed station departure board.\n<p>Parameters are validated using GetStationBoardWithDetails …\n"},{"name":"get_departure_board","full_name":"Ldbws::Service#get_departure_board","type":"instance_method","path":"Ldbws/Service.html#method-i-get_departure_board","snippet":"<p>Retrieves a station departure board.\n<p>Parameters are validated using GetStationBoard, returns a StationBoard …\n"},{"name":"get_departure_board_with_details","full_name":"Ldbws::Service#get_departure_board_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_departure_board_with_details"},{"name":"get_fastest_departures","full_name":"Ldbws::Service#get_fastest_departures","type":"instance_method","path":"Ldbws/Service.html#method-i-get_fastest_departures","snippet":"<p>Retrieves the fastest departures from one station to one or many others.\n<p>Parameters are validated using …\n"},{"name":"get_fastest_departures_with_details","full_name":"Ldbws::Service#get_fastest_departures_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_fastest_departures_with_details","snippet":"<p>Retrieves detailed information about the fastest departures from one station to one or many others.\n<p>Parameters …\n"},{"name":"get_next_departures","full_name":"Ldbws::Service#get_next_departures","type":"instance_method","path":"Ldbws/Service.html#method-i-get_next_departures","snippet":"<p>Retrieves the next departures from one station to one or many others.\n<p>Parameters are validated using …\n"},{"name":"get_next_departures_with_details","full_name":"Ldbws::Service#get_next_departures_with_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_next_departures_with_details","snippet":"<p>Retrieves detailed information about the next departures from one station to one or many others.\n<p>Parameters …\n"},{"name":"get_service_details","full_name":"Ldbws::Service#get_service_details","type":"instance_method","path":"Ldbws/Service.html#method-i-get_service_details","snippet":"<p>Retrieves information about a specific service.\n<p>Parameters are validated using GetServiceDetails, returns …\n"},{"name":"messages","full_name":"Ldbws::Request::ParamValidationError#messages","type":"instance_method","path":"Ldbws/Request/ParamValidationError.html#method-i-messages","snippet":"<p>Returns the validation error messages as a hash.\n"}]};
@@ -0,0 +1,105 @@
1
+ /*
2
+ * SearchNavigation allows movement using the arrow keys through the search results.
3
+ *
4
+ * When using this library you will need to set scrollIntoView to the
5
+ * appropriate function for your layout. Use scrollInWindow if the container
6
+ * is not scrollable and scrollInElement if the container is a separate
7
+ * scrolling region.
8
+ */
9
+ SearchNavigation = new function() {
10
+ this.initNavigation = function() {
11
+ var _this = this;
12
+
13
+ document.addEventListener('keydown', function(e) {
14
+ _this.onkeydown(e);
15
+ });
16
+
17
+ this.navigationActive = true;
18
+ }
19
+
20
+ this.setNavigationActive = function(state) {
21
+ this.navigationActive = state;
22
+ }
23
+
24
+ this.onkeydown = function(e) {
25
+ if (!this.navigationActive) return;
26
+ switch(e.key) {
27
+ case 'ArrowLeft':
28
+ if (this.moveLeft()) e.preventDefault();
29
+ break;
30
+ case 'ArrowUp':
31
+ if (e.key == 'ArrowUp' || e.ctrlKey) {
32
+ if (this.moveUp()) e.preventDefault();
33
+ }
34
+ break;
35
+ case 'ArrowRight':
36
+ if (this.moveRight()) e.preventDefault();
37
+ break;
38
+ case 'ArrowDown':
39
+ if (e.key == 'ArrowDown' || e.ctrlKey) {
40
+ if (this.moveDown()) e.preventDefault();
41
+ }
42
+ break;
43
+ case 'Enter':
44
+ if (this.current) e.preventDefault();
45
+ this.select(this.current);
46
+ break;
47
+ }
48
+ if (e.ctrlKey && e.shiftKey) this.select(this.current);
49
+ }
50
+
51
+ this.moveRight = function() {
52
+ }
53
+
54
+ this.moveLeft = function() {
55
+ }
56
+
57
+ this.move = function(isDown) {
58
+ }
59
+
60
+ this.moveUp = function() {
61
+ return this.move(false);
62
+ }
63
+
64
+ this.moveDown = function() {
65
+ return this.move(true);
66
+ }
67
+
68
+ /*
69
+ * Scrolls to the given element in the scrollable element view.
70
+ */
71
+ this.scrollInElement = function(element, view) {
72
+ var offset, viewHeight, viewScroll, height;
73
+ offset = element.offsetTop;
74
+ height = element.offsetHeight;
75
+ viewHeight = view.offsetHeight;
76
+ viewScroll = view.scrollTop;
77
+
78
+ if (offset - viewScroll + height > viewHeight) {
79
+ view.scrollTop = offset - viewHeight + height;
80
+ }
81
+ if (offset < viewScroll) {
82
+ view.scrollTop = offset;
83
+ }
84
+ }
85
+
86
+ /*
87
+ * Scrolls to the given element in the window. The second argument is
88
+ * ignored
89
+ */
90
+ this.scrollInWindow = function(element, ignored) {
91
+ var offset, viewHeight, viewScroll, height;
92
+ offset = element.offsetTop;
93
+ height = element.offsetHeight;
94
+ viewHeight = window.innerHeight;
95
+ viewScroll = window.scrollY;
96
+
97
+ if (offset - viewScroll + height > viewHeight) {
98
+ window.scrollTo(window.scrollX, offset - viewHeight + height);
99
+ }
100
+ if (offset < viewScroll) {
101
+ window.scrollTo(window.scrollX, offset);
102
+ }
103
+ }
104
+ }
105
+