mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-23 03:59:30 -07:00
non-jquery autocomplete, needs more keyboard integration
This commit is contained in:
@@ -4,7 +4,6 @@ module.exports = {
|
|||||||
commonjs: true,
|
commonjs: true,
|
||||||
es6: true,
|
es6: true,
|
||||||
node: true,
|
node: true,
|
||||||
jquery: true,
|
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
'airbnb-base',
|
'airbnb-base',
|
||||||
@@ -30,7 +29,7 @@ module.exports = {
|
|||||||
'error',
|
'error',
|
||||||
'tab',
|
'tab',
|
||||||
{
|
{
|
||||||
SwitchCase: 1
|
SwitchCase: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'no-tabs': 0,
|
'no-tabs': 0,
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ const compressJsData = () => src(jsSourcesData)
|
|||||||
.pipe(dest(RESOURCES_PATH));
|
.pipe(dest(RESOURCES_PATH));
|
||||||
|
|
||||||
const jsVendorSources = [
|
const jsVendorSources = [
|
||||||
'server/scripts/vendor/auto/jquery.js',
|
|
||||||
'server/scripts/vendor/jquery.autocomplete.min.js',
|
|
||||||
'server/scripts/vendor/auto/nosleep.js',
|
'server/scripts/vendor/auto/nosleep.js',
|
||||||
'server/scripts/vendor/auto/swiped-events.js',
|
'server/scripts/vendor/auto/swiped-events.js',
|
||||||
'server/scripts/vendor/auto/suncalc.js',
|
'server/scripts/vendor/auto/suncalc.js',
|
||||||
@@ -173,6 +171,6 @@ const buildDist = series(clean, parallel(buildJs, compressJsData, compressJsVend
|
|||||||
|
|
||||||
// upload_images could be in parallel with upload, but _images logs a lot and has little changes
|
// upload_images could be in parallel with upload, but _images logs a lot and has little changes
|
||||||
// by running upload last the majority of the changes will be at the bottom of the log for easy viewing
|
// by running upload last the majority of the changes will be at the bottom of the log for easy viewing
|
||||||
const publishFrontend = series(buildDist, uploadImages, upload, invalidate);
|
const publishFrontend = series(buildDist, uploadImages, upload, invalidate);
|
||||||
|
|
||||||
export default publishFrontend;
|
export default publishFrontend;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ const vendorFiles = [
|
|||||||
'./node_modules/luxon/build/es6/luxon.js',
|
'./node_modules/luxon/build/es6/luxon.js',
|
||||||
'./node_modules/luxon/build/es6/luxon.js.map',
|
'./node_modules/luxon/build/es6/luxon.js.map',
|
||||||
'./node_modules/nosleep.js/dist/NoSleep.js',
|
'./node_modules/nosleep.js/dist/NoSleep.js',
|
||||||
'./node_modules/jquery/dist/jquery.js',
|
|
||||||
'./node_modules/suncalc/suncalc.js',
|
'./node_modules/suncalc/suncalc.js',
|
||||||
'./node_modules/swiped-events/src/swiped-events.js',
|
'./node_modules/swiped-events/src/swiped-events.js',
|
||||||
];
|
];
|
||||||
|
|||||||
15
package-lock.json
generated
15
package-lock.json
generated
@@ -27,8 +27,6 @@
|
|||||||
"gulp-s3-upload": "^1.7.3",
|
"gulp-s3-upload": "^1.7.3",
|
||||||
"gulp-sass": "^5.1.0",
|
"gulp-sass": "^5.1.0",
|
||||||
"gulp-terser": "^2.0.0",
|
"gulp-terser": "^2.0.0",
|
||||||
"jquery": "^3.6.0",
|
|
||||||
"jquery-touchswipe": "^1.6.19",
|
|
||||||
"luxon": "^3.0.0",
|
"luxon": "^3.0.0",
|
||||||
"nosleep.js": "^0.12.0",
|
"nosleep.js": "^0.12.0",
|
||||||
"sass": "^1.54.0",
|
"sass": "^1.54.0",
|
||||||
@@ -6494,19 +6492,6 @@
|
|||||||
"node": ">= 0.6.0"
|
"node": ">= 0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jquery": {
|
|
||||||
"version": "3.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
|
||||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/jquery-touchswipe": {
|
|
||||||
"version": "1.6.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/jquery-touchswipe/-/jquery-touchswipe-1.6.19.tgz",
|
|
||||||
"integrity": "sha512-b0BGje9reNRU3u6ksAK9QqnX7yBRgLNe/wYG7DOfyDlhBlYjayIT8bSOHmcuvptIDW/ubM9CTW/mnZf9Rohuow==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
|||||||
@@ -21,8 +21,6 @@
|
|||||||
"homepage": "https://github.com/netbymatt/ws4kp#readme",
|
"homepage": "https://github.com/netbymatt/ws4kp#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"del": "^7.1.0",
|
"del": "^7.1.0",
|
||||||
"jquery": "^3.6.0",
|
|
||||||
"jquery-touchswipe": "^1.6.19",
|
|
||||||
"luxon": "^3.0.0",
|
"luxon": "^3.0.0",
|
||||||
"nosleep.js": "^0.12.0",
|
"nosleep.js": "^0.12.0",
|
||||||
"suncalc": "^1.8.0",
|
"suncalc": "^1.8.0",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
import { round2 } from './modules/utils/units.mjs';
|
import { round2 } from './modules/utils/units.mjs';
|
||||||
import { parseQueryString } from './modules/share.mjs';
|
import { parseQueryString } from './modules/share.mjs';
|
||||||
import settings from './modules/settings.mjs';
|
import settings from './modules/settings.mjs';
|
||||||
|
import AutoComplete from './modules/autocomplete.mjs';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
init();
|
init();
|
||||||
@@ -56,7 +57,7 @@ const init = () => {
|
|||||||
document.addEventListener('keydown', documentKeydown);
|
document.addEventListener('keydown', documentKeydown);
|
||||||
document.addEventListener('touchmove', (e) => { if (document.fullscreenElement) e.preventDefault(); });
|
document.addEventListener('touchmove', (e) => { if (document.fullscreenElement) e.preventDefault(); });
|
||||||
|
|
||||||
$(TXT_ADDRESS_SELECTOR).devbridgeAutocomplete({
|
const autoComplete = new AutoComplete(document.querySelector(TXT_ADDRESS_SELECTOR), {
|
||||||
serviceUrl: 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/suggest',
|
serviceUrl: 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/suggest',
|
||||||
deferRequestBy: 300,
|
deferRequestBy: 300,
|
||||||
paramName: 'text',
|
paramName: 'text',
|
||||||
@@ -76,13 +77,12 @@ const init = () => {
|
|||||||
minChars: 3,
|
minChars: 3,
|
||||||
showNoSuggestionNotice: true,
|
showNoSuggestionNotice: true,
|
||||||
noSuggestionNotice: 'No results found. Please try a different search string.',
|
noSuggestionNotice: 'No results found. Please try a different search string.',
|
||||||
onSelect(suggestion) { autocompleteOnSelect(suggestion, this); },
|
onSelect(suggestion) { autocompleteOnSelect(suggestion); },
|
||||||
width: 490,
|
width: 490,
|
||||||
});
|
});
|
||||||
|
|
||||||
const formSubmit = () => {
|
const formSubmit = () => {
|
||||||
const ac = $(TXT_ADDRESS_SELECTOR).devbridgeAutocomplete();
|
if (autoComplete.suggestions[0]) autoComplete.suggestionsContainer.children[0].trigger('click');
|
||||||
if (ac.suggestions[0]) $(ac.suggestionsContainer.children[0]).trigger('click');
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -133,10 +133,7 @@ const init = () => {
|
|||||||
document.querySelector('#container').addEventListener('swiped-right', () => swipeCallBack('right'));
|
document.querySelector('#container').addEventListener('swiped-right', () => swipeCallBack('right'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const autocompleteOnSelect = async (suggestion, elem) => {
|
const autocompleteOnSelect = async (suggestion) => {
|
||||||
// Do not auto get the same city twice.
|
|
||||||
if (elem.previousSuggestionValue === suggestion.value) return;
|
|
||||||
|
|
||||||
const data = await json('https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find', {
|
const data = await json('https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find', {
|
||||||
data: {
|
data: {
|
||||||
text: suggestion.value,
|
text: suggestion.value,
|
||||||
|
|||||||
229
server/scripts/modules/autocomplete.mjs
Normal file
229
server/scripts/modules/autocomplete.mjs
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
/* eslint-disable default-case */
|
||||||
|
import { json } from './utils/fetch.mjs';
|
||||||
|
|
||||||
|
const KEYS = {
|
||||||
|
ESC: 27,
|
||||||
|
TAB: 9,
|
||||||
|
RETURN: 13,
|
||||||
|
LEFT: 37,
|
||||||
|
UP: 38,
|
||||||
|
RIGHT: 39,
|
||||||
|
DOWN: 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_OPTIONS = {
|
||||||
|
autoSelectFirst: false,
|
||||||
|
serviceUrl: null,
|
||||||
|
lookup: null,
|
||||||
|
onSelect: null,
|
||||||
|
onHint: null,
|
||||||
|
width: 'auto',
|
||||||
|
minChars: 1,
|
||||||
|
maxHeight: 300,
|
||||||
|
deferRequestBy: 0,
|
||||||
|
params: {},
|
||||||
|
delimiter: null,
|
||||||
|
zIndex: 9999,
|
||||||
|
type: 'GET',
|
||||||
|
noCache: false,
|
||||||
|
preserveInput: false,
|
||||||
|
containerClass: 'autocomplete-suggestions',
|
||||||
|
tabDisabled: false,
|
||||||
|
dataType: 'text',
|
||||||
|
currentRequest: null,
|
||||||
|
triggerSelectOnValidInput: true,
|
||||||
|
preventBadQueries: true,
|
||||||
|
paramName: 'query',
|
||||||
|
transformResult: (a) => a,
|
||||||
|
showNoSuggestionNotice: false,
|
||||||
|
noSuggestionNotice: 'No results',
|
||||||
|
orientation: 'bottom',
|
||||||
|
forceFixPosition: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const escapeRegExChars = (string) => string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||||
|
|
||||||
|
const formatResult = (suggestion, search) => {
|
||||||
|
// Do not replace anything if the current value is empty
|
||||||
|
if (!search) {
|
||||||
|
return suggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = `(${escapeRegExChars(search)})`;
|
||||||
|
|
||||||
|
return suggestion
|
||||||
|
.replace(new RegExp(pattern, 'gi'), '<strong>$1</strong>')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/<(\/?strong)>/g, '<$1>');
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoComplete {
|
||||||
|
constructor(elem, options) {
|
||||||
|
this.options = { ...DEFAULT_OPTIONS, ...options };
|
||||||
|
this.elem = elem;
|
||||||
|
this.selectedItem = -1;
|
||||||
|
this.onChangeTimeout = null;
|
||||||
|
this.currentValue = '';
|
||||||
|
this.suggestions = [];
|
||||||
|
this.cachedResponses = {};
|
||||||
|
|
||||||
|
// create and add the results container
|
||||||
|
const results = document.createElement('div');
|
||||||
|
results.style.display = 'none';
|
||||||
|
results.classList.add(this.options.containerClass);
|
||||||
|
results.style.width = (typeof this.options.width === 'string') ? this.options.width : `${this.options.width}px`;
|
||||||
|
results.style.zIndex = this.options.zIndex;
|
||||||
|
results.style.maxHeight = `${this.options.maxHeight}px`;
|
||||||
|
results.style.overflowX = 'hidden';
|
||||||
|
results.addEventListener('mouseover', (e) => this.mouseOver(e));
|
||||||
|
results.addEventListener('mouseout', (e) => this.mouseOut(e));
|
||||||
|
results.addEventListener('click', (e) => this.click(e));
|
||||||
|
|
||||||
|
this.results = results;
|
||||||
|
this.elem.after(results);
|
||||||
|
|
||||||
|
// add handlers for typing text
|
||||||
|
this.elem.addEventListener('keyup', (e) => this.keyUp(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseOver(e) {
|
||||||
|
// suggestion line
|
||||||
|
if (e.target?.classList?.contains('suggestion')) {
|
||||||
|
e.target.classList.add('selected');
|
||||||
|
this.selectedItem = parseInt(e.target.dataset.item, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseOut(e) {
|
||||||
|
// suggestion line
|
||||||
|
if (e.target?.classList?.contains('suggestion')) {
|
||||||
|
e.target.classList.remove('selected');
|
||||||
|
this.selectedItem = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
click(e) {
|
||||||
|
// suggestion line
|
||||||
|
if (e.target?.classList?.contains('suggestion')) {
|
||||||
|
// get the entire suggestion
|
||||||
|
const suggestion = this.suggestions[parseInt(e.target.dataset.item, 10)];
|
||||||
|
this.options.onSelect(suggestion);
|
||||||
|
this.elem.value = suggestion.value;
|
||||||
|
this.hideSuggestions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideSuggestions() {
|
||||||
|
this.results.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
showSuggestions() {
|
||||||
|
this.results.style.removeProperty('display');
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSuggestions() {
|
||||||
|
this.results.innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
keyUp(e) {
|
||||||
|
// ignore some keys
|
||||||
|
switch (e.which) {
|
||||||
|
case KEYS.UP:
|
||||||
|
case KEYS.DOWN:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTimeout(this.onChangeTimeout);
|
||||||
|
|
||||||
|
if (this.currentValue !== this.elem.value) {
|
||||||
|
if (this.options.deferRequestBy > 0) {
|
||||||
|
// defer lookup during rapid key presses
|
||||||
|
this.onChangeTimeout = setTimeout(() => {
|
||||||
|
this.onValueChange();
|
||||||
|
}, this.options.deferRequestBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onValueChange() {
|
||||||
|
clearTimeout(this.onValueChange);
|
||||||
|
|
||||||
|
// confirm value actually changed
|
||||||
|
if (this.currentValue === this.elem.value) return;
|
||||||
|
// store new value
|
||||||
|
this.currentValue = this.elem.value;
|
||||||
|
|
||||||
|
// clear the selected index
|
||||||
|
this.selectedItem = -1;
|
||||||
|
this.results.querySelectorAll('div').forEach((elem) => elem.classList.remove('selected'));
|
||||||
|
|
||||||
|
// if less than minimum don't query api
|
||||||
|
if (this.currentValue.length < this.options.minChars) {
|
||||||
|
this.hideSuggestions();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getSuggestions(this.currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSuggestions(search) {
|
||||||
|
// assemble options
|
||||||
|
const searchOptions = { ...this.options.params };
|
||||||
|
searchOptions[this.options.paramName] = search;
|
||||||
|
|
||||||
|
// build search url
|
||||||
|
const url = new URL(this.options.serviceUrl);
|
||||||
|
Object.entries(searchOptions).forEach(([key, value]) => {
|
||||||
|
url.searchParams.append(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = this.cachedResponses[search];
|
||||||
|
if (!result) {
|
||||||
|
// make the request
|
||||||
|
const resultRaw = await json(url);
|
||||||
|
|
||||||
|
// use the provided parser
|
||||||
|
result = this.options.transformResult(resultRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store suggestions
|
||||||
|
this.cachedResponses[search] = result.suggestions;
|
||||||
|
this.suggestions = result.suggestions;
|
||||||
|
|
||||||
|
// populate the suggestion area
|
||||||
|
this.populateSuggestions();
|
||||||
|
}
|
||||||
|
|
||||||
|
populateSuggestions() {
|
||||||
|
if (this.suggestions.length === 0) {
|
||||||
|
if (this.options.showNoSuggestionNotice) {
|
||||||
|
this.noSuggestionNotice();
|
||||||
|
} else {
|
||||||
|
this.hideSuggestions();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the list
|
||||||
|
const suggestionElems = this.suggestions.map((suggested, idx) => {
|
||||||
|
const elem = document.createElement('div');
|
||||||
|
elem.classList.add('suggestion');
|
||||||
|
elem.dataset.item = idx;
|
||||||
|
elem.innerHTML = (formatResult(suggested.value, this.currentValue));
|
||||||
|
return elem.outerHTML;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.results.innerHTML = suggestionElems.join('');
|
||||||
|
this.showSuggestions();
|
||||||
|
}
|
||||||
|
|
||||||
|
noSuggestionNotice() {
|
||||||
|
this.results.innerHTML = `<div>${this.options.noSuggestionNotice}</div>`;
|
||||||
|
this.showSuggestions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AutoComplete;
|
||||||
10716
server/scripts/vendor/auto/jquery.js
vendored
10716
server/scripts/vendor/auto/jquery.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -106,23 +106,26 @@ body {
|
|||||||
.autocomplete-suggestions {
|
.autocomplete-suggestions {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border: 1px solid #000000;
|
border: 1px solid #000000;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.autocomplete-suggestion {
|
div {
|
||||||
/*padding: 2px 5px;*/
|
/*padding: 2px 5px;*/
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-size: 16pt;
|
font-size: 16pt;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: #0000ff;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.autocomplete-selected {
|
|
||||||
background-color: #0000ff;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#divTwc {
|
#divTwc {
|
||||||
|
|||||||
270
views/index.ejs
270
views/index.ejs
@@ -3,149 +3,151 @@
|
|||||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>WeatherStar 4000+</title>
|
<title>WeatherStar 4000+</title>
|
||||||
<meta name="description" content="Web based WeatherStar 4000 simulator that reports current and forecast weather conditions plus a few extras!" />
|
<meta name="description"
|
||||||
<meta name="keywords" content="WeatherStar 4000+" />
|
content="Web based WeatherStar 4000 simulator that reports current and forecast weather conditions plus a few extras!" />
|
||||||
<meta name="author" content="Matt Walsh" />
|
<meta name="keywords" content="WeatherStar 4000+" />
|
||||||
<meta name="application-name" content="WeatherStar 4000+" />
|
<meta name="author" content="Matt Walsh" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1">
|
<meta name="application-name" content="WeatherStar 4000+" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<link rel="manifest" href="manifest.json" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<link rel="icon" href="images/Logo192.png" />
|
<link rel="manifest" href="manifest.json" />
|
||||||
|
<link rel="icon" href="images/Logo192.png" />
|
||||||
|
|
||||||
<% if (production) { %>
|
<% if (production) { %>
|
||||||
<link rel="stylesheet" type="text/css" href="resources/ws.min.css?_=<%=production%>" />
|
<link rel="stylesheet" type="text/css" href="resources/ws.min.css?_=<%=production%>" />
|
||||||
<script type="text/javascript" src="resources/data.min.js?_=<%=production%>"></script>
|
<script type="text/javascript" src="resources/data.min.js?_=<%=production%>"></script>
|
||||||
<script type="text/javascript" src="resources/vendor.min.js?_=<%=production%>"></script>
|
<script type="text/javascript" src="resources/vendor.min.js?_=<%=production%>"></script>
|
||||||
<script type="text/javascript" src="resources/ws.min.js?_=<%=production%>"></script>
|
<script type="text/javascript" src="resources/ws.min.js?_=<%=production%>"></script>
|
||||||
<script type="text/javascript" src="scripts/custom.js?_=<%=production%>"></script>
|
<script type="text/javascript" src="scripts/custom.js?_=<%=production%>"></script>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<link rel="stylesheet" type="text/css" href="styles/main.css" />
|
<link rel="stylesheet" type="text/css" href="styles/main.css" />
|
||||||
<script type="text/javascript" src="scripts/vendor/auto/jquery.js"></script>
|
<script type="text/javascript" src="scripts/vendor/auto/nosleep.js"></script>
|
||||||
<script type="text/javascript" src="scripts/vendor/jquery.autocomplete.min.js"></script>
|
<script type="text/javascript" src="scripts/vendor/auto/swiped-events.js"></script>
|
||||||
<script type="text/javascript" src="scripts/vendor/auto/nosleep.js"></script>
|
<script type="text/javascript" src="scripts/vendor/auto/suncalc.js"></script>
|
||||||
<script type="text/javascript" src="scripts/vendor/auto/swiped-events.js"></script>
|
<script type="module" src="scripts/modules/hazards.mjs"></script>
|
||||||
<script type="text/javascript" src="scripts/vendor/auto/suncalc.js"></script>
|
<script type="module" src="scripts/modules/currentweatherscroll.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/hazards.mjs"></script>
|
<script type="module" src="scripts/modules/currentweather.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/currentweatherscroll.mjs"></script>
|
<script type="module" src="scripts/modules/almanac.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/currentweather.mjs"></script>
|
<script type="module" src="scripts/modules/icons.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/almanac.mjs"></script>
|
<script type="module" src="scripts/modules/extendedforecast.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/icons.mjs"></script>
|
<script type="module" src="scripts/modules/hourly-graph.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/extendedforecast.mjs"></script>
|
<script type="module" src="scripts/modules/hourly.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/hourly-graph.mjs"></script>
|
<script type="module" src="scripts/modules/latestobservations.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/hourly.mjs"></script>
|
<script type="module" src="scripts/modules/localforecast.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/latestobservations.mjs"></script>
|
<script type="module" src="scripts/modules/radar.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/localforecast.mjs"></script>
|
<script type="module" src="scripts/modules/regionalforecast.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/radar.mjs"></script>
|
<script type="module" src="scripts/modules/travelforecast.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/regionalforecast.mjs"></script>
|
<script type="module" src="scripts/modules/progress.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/travelforecast.mjs"></script>
|
<script type="module" src="scripts/modules/radar.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/progress.mjs"></script>
|
<script type="module" src="scripts/modules/settings.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/radar.mjs"></script>
|
<script type="module" src="scripts/index.mjs"></script>
|
||||||
<script type="module" src="scripts/modules/settings.mjs"></script>
|
<script type="text/javascript" src="scripts/custom.js"></script>
|
||||||
<script type="module" src="scripts/index.mjs"></script>
|
<!-- data -->
|
||||||
<script type="text/javascript" src="scripts/custom.js"></script>
|
<script type="text/javascript" src="scripts/data/travelcities.js"></script>
|
||||||
<!-- data -->
|
<script type="text/javascript" src="scripts/data/regionalcities.js"></script>
|
||||||
<script type="text/javascript" src="scripts/data/travelcities.js"></script>
|
<script type="text/javascript" src="scripts/data/stations.js"></script>
|
||||||
<script type="text/javascript" src="scripts/data/regionalcities.js"></script>
|
|
||||||
<script type="text/javascript" src="scripts/data/stations.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="scripts/custom.js"></script>
|
<script type="text/javascript" src="scripts/custom.js"></script>
|
||||||
|
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|
||||||
<div id="divQuery">
|
<div id="divQuery">
|
||||||
<input id="txtAddress" type="text" value="" placeholder="Zip or City, State" />
|
<input id="txtAddress" type="text" value="" placeholder="Zip or City, State" />
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button id="btnGetGps" type="button" title="Get GPS Location"><img src="images/nav/ic_gps_fixed_black_18dp_1x.png" class="light"/>
|
<button id="btnGetGps" type="button" title="Get GPS Location"><img src="images/nav/ic_gps_fixed_black_18dp_1x.png"
|
||||||
<img src="images/nav/ic_gps_fixed_white_18dp_1x.png" class="dark"/>
|
class="light" />
|
||||||
|
<img src="images/nav/ic_gps_fixed_white_18dp_1x.png" class="dark" />
|
||||||
</button>
|
</button>
|
||||||
<button id="btnGetLatLng" type="submit">GO</button>
|
<button id="btnGetLatLng" type="submit">GO</button>
|
||||||
<button id="btnClearQuery" type="reset">Reset</button>
|
<button id="btnClearQuery" type="reset">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="version" style="display:none">
|
<div id="version" style="display:none">
|
||||||
<%- version %>
|
<%- version %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="divTwc">
|
<div id="divTwc">
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<div id="loading" width="640" height="480">
|
<div id="loading" width="640" height="480">
|
||||||
<div>
|
<div>
|
||||||
<div class="title">WeatherStar 4000+</div>
|
<div class="title">WeatherStar 4000+</div>
|
||||||
<div class="version">v<%- version %></div>
|
<div class="version">v<%- version %></div>
|
||||||
<div class="instructions">Enter your location above to continue</div>
|
<div class="instructions">Enter your location above to continue</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="progress-html" class="weather-display">
|
<div id="progress-html" class="weather-display">
|
||||||
<%- include('partials/progress.ejs') %>
|
<%- include('partials/progress.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="hourly-html" class="weather-display">
|
<div id="hourly-html" class="weather-display">
|
||||||
<%- include('partials/hourly.ejs') %>
|
<%- include('partials/hourly.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="hourly-graph-html" class="weather-display">
|
<div id="hourly-graph-html" class="weather-display">
|
||||||
<%- include('partials/hourly-graph.ejs') %>
|
<%- include('partials/hourly-graph.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="travel-html" class="weather-display">
|
<div id="travel-html" class="weather-display">
|
||||||
<%- include('partials/travel.ejs') %>
|
<%- include('partials/travel.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="current-weather-html" class="weather-display">
|
<div id="current-weather-html" class="weather-display">
|
||||||
<%- include('partials/current-weather.ejs') %>
|
<%- include('partials/current-weather.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="local-forecast-html" class="weather-display">
|
<div id="local-forecast-html" class="weather-display">
|
||||||
<%- include('partials/local-forecast.ejs') %>
|
<%- include('partials/local-forecast.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="latest-observations-html" class="weather-display">
|
<div id="latest-observations-html" class="weather-display">
|
||||||
<%- include('partials/latest-observations.ejs') %>
|
<%- include('partials/latest-observations.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="regional-forecast-html" class="weather-display">
|
<div id="regional-forecast-html" class="weather-display">
|
||||||
<%- include('partials/regional-forecast.ejs') %>
|
<%- include('partials/regional-forecast.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="almanac-html" class="weather-display">
|
<div id="almanac-html" class="weather-display">
|
||||||
<%- include('partials/almanac.ejs') %>
|
<%- include('partials/almanac.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="extended-forecast-html" class="weather-display">
|
<div id="extended-forecast-html" class="weather-display">
|
||||||
<%- include('partials/extended-forecast.ejs') %>
|
<%- include('partials/extended-forecast.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="radar-html" class="weather-display">
|
<div id="radar-html" class="weather-display">
|
||||||
<%- include('partials/radar.ejs') %>
|
<%- include('partials/radar.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
<div id="hazards-html" class="weather-display">
|
<div id="hazards-html" class="weather-display">
|
||||||
<%- include('partials/hazards.ejs') %>
|
<%- include('partials/hazards.ejs') %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="divTwcBottom">
|
<div id="divTwcBottom">
|
||||||
<div id="divTwcBottomLeft">
|
<div id="divTwcBottomLeft">
|
||||||
<img id="NavigateMenu" class="navButton" src="images/nav/ic_menu_white_24dp_2x.png" title="Menu" />
|
<img id="NavigateMenu" class="navButton" src="images/nav/ic_menu_white_24dp_2x.png" title="Menu" />
|
||||||
<img id="NavigatePrevious" class="navButton" src="images/nav/ic_skip_previous_white_24dp_2x.png" title="Previous" />
|
<img id="NavigatePrevious" class="navButton" src="images/nav/ic_skip_previous_white_24dp_2x.png"
|
||||||
<img id="NavigateNext" class="navButton" src="images/nav/ic_skip_next_white_24dp_2x.png" title="Next" />
|
title="Previous" />
|
||||||
<img id="NavigatePlay" class="navButton" src="images/nav/ic_play_arrow_white_24dp_2x.png" title="Play" />
|
<img id="NavigateNext" class="navButton" src="images/nav/ic_skip_next_white_24dp_2x.png" title="Next" />
|
||||||
</div>
|
<img id="NavigatePlay" class="navButton" src="images/nav/ic_play_arrow_white_24dp_2x.png" title="Play" />
|
||||||
<div id="divTwcBottomMiddle">
|
</div>
|
||||||
<img id="NavigateRefresh" class="navButton" src="images/nav/ic_refresh_white_24dp_2x.png" title="Refresh" />
|
<div id="divTwcBottomMiddle">
|
||||||
</div>
|
<img id="NavigateRefresh" class="navButton" src="images/nav/ic_refresh_white_24dp_2x.png" title="Refresh" />
|
||||||
<div id="divTwcBottomRight">
|
</div>
|
||||||
<img id="ToggleFullScreen" class="navButton" src="images/nav/ic_fullscreen_white_24dp_2x.png" title="Enter Fullscreen" />
|
<div id="divTwcBottomRight">
|
||||||
</div>
|
<img id="ToggleFullScreen" class="navButton" src="images/nav/ic_fullscreen_white_24dp_2x.png"
|
||||||
</div>
|
title="Enter Fullscreen" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<a href="https://github.com/netbymatt/ws4kp#weatherstar-4000">More information</a>
|
<a href="https://github.com/netbymatt/ws4kp#weatherstar-4000">More information</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='heading'>Selected displays</div>
|
<div class='heading'>Selected displays</div>
|
||||||
<div id='enabledDisplays'>
|
<div id='enabledDisplays'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='heading'>Settings</div>
|
<div class='heading'>Settings</div>
|
||||||
<div id='settings'>
|
<div id='settings'>
|
||||||
@@ -156,22 +158,24 @@
|
|||||||
<a href='' id='share-link'>Copy Permalink</a> <span id="share-link-copied">Link copied to clipboard!</span>
|
<a href='' id='share-link'>Copy Permalink</a> <span id="share-link-copied">Link copied to clipboard!</span>
|
||||||
<div id="share-link-instructions">
|
<div id="share-link-instructions">
|
||||||
Copy this long URL:
|
Copy this long URL:
|
||||||
<input type='text' id="share-link-url"></div>
|
<input type='text' id="share-link-url">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class='heading'>Forecast Information</div>
|
<div class='heading'>Forecast Information</div>
|
||||||
<div id="divInfo">
|
<div id="divInfo">
|
||||||
Location: <span id="spanCity"></span> <span id="spanState"></span><br />
|
Location: <span id="spanCity"></span> <span id="spanState"></span><br />
|
||||||
Station Id: <span id="spanStationId"></span><br />
|
Station Id: <span id="spanStationId"></span><br />
|
||||||
Radar Id: <span id="spanRadarId"></span><br />
|
Radar Id: <span id="spanRadarId"></span><br />
|
||||||
Zone Id: <span id="spanZoneId"></span><br />
|
Zone Id: <span id="spanZoneId"></span><br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="divRefresh">
|
<div id="divRefresh">
|
||||||
Last Update: <span id="spanLastRefresh">(None)</span><br />
|
Last Update: <span id="spanLastRefresh">(None)</span><br />
|
||||||
<input id="chkAutoRefresh" name="chkAutoRefresh" type="checkbox" /><label id="lblRefreshCountDown" for="chkAutoRefresh">Auto Refresh: <span id="spanRefreshCountDown">--:--</span></label>
|
<input id="chkAutoRefresh" name="chkAutoRefresh" type="checkbox" /><label id="lblRefreshCountDown"
|
||||||
</div>
|
for="chkAutoRefresh">Auto Refresh: <span id="spanRefreshCountDown">--:--</span></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user