Files
archived-teslamate/assets/js/hooks.js
T

322 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const LANG = navigator.languages
? navigator.languages[0]
: navigator.language || navigator.userLanguage;
function toLocalTime(dateStr, opts) {
const date = new Date(dateStr);
return date instanceof Date && !isNaN(date.valueOf())
? date.toLocaleTimeString(LANG, opts)
: "";
}
function toLocalDate(dateStr, opts) {
const date = new Date(dateStr);
return date instanceof Date && !isNaN(date.valueOf())
? date.toLocaleDateString(LANG, opts)
: "";
}
export const Dropdown = {
mounted() {
const $el = this.el;
$el.querySelector("button").addEventListener("click", (e) => {
e.stopPropagation();
$el.classList.toggle("is-active");
});
document.addEventListener("click", () => {
$el.classList.remove("is-active");
});
},
};
export const LocalTime = {
mounted() {
this.el.innerText = toLocalTime(this.el.dataset.date);
},
updated() {
this.el.innerText = toLocalTime(this.el.dataset.date);
},
};
export const LocalTimeRange = {
exec() {
const date = toLocalDate(this.el.dataset.startDate, {
year: "numeric",
month: "short",
day: "numeric",
});
const time = [this.el.dataset.startDate, this.el.dataset.endDate]
.map((date) =>
toLocalTime(date, { hour: "2-digit", minute: "2-digit", hour12: false })
)
.join(" ");
this.el.innerText = `${date}, ${time}`;
},
mounted() {
this.exec();
},
updated() {
this.exec();
},
};
export const ConfirmGeoFenceDeletion = {
mounted() {
const { id, msg } = this.el.dataset;
this.el.addEventListener("click", () => {
if (window.confirm(msg)) {
this.pushEvent("delete", { id });
}
});
},
};
import {
Map as M,
TileLayer,
LatLng,
Control,
Marker,
Icon,
Circle,
CircleMarker,
} from "leaflet";
import markerIcon from "leaflet/dist/images/marker-icon.png";
import markerShadow from "leaflet/dist/images/marker-shadow.png";
const icon = new Icon({
iconUrl: markerIcon,
shadowUrl: markerShadow,
iconAnchor: [12, 40],
popupAnchor: [0, -25],
});
const DirectionArrow = CircleMarker.extend({
initialize(latLng, heading, options) {
this._heading = heading;
CircleMarker.prototype.initialize.call(this, latLng, {
fillOpacity: 1,
radius: 5,
...options,
});
},
setHeading(heading) {
this._heading = heading;
this.redraw();
},
_updatePath() {
const { x, y } = this._point;
if (this._heading === "")
return CircleMarker.prototype._updatePath.call(this);
this.getElement().setAttributeNS(
null,
"transform",
`translate(${x},${y}) rotate(${this._heading})`
);
const path = this._empty() ? "" : `M0,${3} L-4,${5} L0,${-5} L4,${5} z}`;
this._renderer._setPath(this, path);
},
});
function createMap(opts) {
const map = new M(opts.elId != null ? `map_${opts.elId}` : "map", opts);
const osm = new TileLayer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
{ maxZoom: 19 }
);
if (opts.enableHybridLayer) {
const hybrid = new TileLayer(
"http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}",
{ maxZoom: 20, subdomains: ["mt0", "mt1", "mt2", "mt3"] }
);
new Control.Layers({ OSM: osm, Hybrid: hybrid }).addTo(map);
}
map.addLayer(osm);
return map;
}
export const SimpleMap = {
mounted() {
const $position = document.querySelector(`#position_${this.el.dataset.id}`);
const map = createMap({
elId: this.el.dataset.id,
zoomControl: !!this.el.dataset.zoom,
boxZoom: false,
doubleClickZoom: false,
keyboard: false,
scrollWheelZoom: false,
tap: false,
dragging: false,
touchZoom: false,
});
const isArrow = this.el.dataset.marker === "arrow";
const [lat, lng, heading] = $position.value.split(",");
const marker = isArrow
? new DirectionArrow([lat, lng], heading)
: new Marker([lat, lng], { icon });
map.setView([lat, lng], 17);
marker.addTo(map);
map.removeControl(map.zoomControl);
map.on('mouseover', function(e) { map.addControl( map.zoomControl ); });
map.on('mouseout', function(e) { map.removeControl( map.zoomControl ); });
if (isArrow) {
const setView = () => {
const [lat, lng, heading] = $position.value.split(",");
marker.setHeading(heading);
marker.setLatLng([lat, lng]);
map.setView([lat, lng], map.getZoom());
};
$position.addEventListener("change", setView);
}
},
};
export const TriggerChange = {
updated() {
this.el.dispatchEvent(new CustomEvent("change"));
},
};
import("leaflet-control-geocoder");
import("@geoman-io/leaflet-geoman-free");
export const Map = {
mounted() {
const geoFence = (name) =>
document.querySelector(`input[name='geo_fence[${name}]']`);
const $radius = geoFence("radius");
const $latitude = geoFence("latitude");
const $longitude = geoFence("longitude");
const location = new LatLng($latitude.value, $longitude.value);
const controlOpts = {
position: "topleft",
cutPolygon: false,
drawCircle: false,
drawCircleMarker: false,
drawMarker: false,
drawPolygon: false,
drawPolyline: false,
drawRectangle: false,
removalMode: false,
};
const editOpts = {
allowSelfIntersection: false,
preventMarkerRemoval: true,
};
const map = createMap({ enableHybridLayer: true });
map.setView(location, 17, { animate: false });
map.pm.setLang(LANG);
map.pm.addControls(controlOpts);
map.pm.enableGlobalEditMode(editOpts);
const circle = new Circle(location, { radius: $radius.value })
.addTo(map)
.on("pm:edit", (e) => {
const { lat, lng } = e.target.getLatLng();
const radius = Math.round(e.target.getRadius());
$radius.value = radius;
$latitude.value = lat;
$longitude.value = lng;
const mBox = map.getBounds();
const cBox = circle.getBounds();
const bounds = mBox.contains(cBox) ? mBox : cBox;
map.fitBounds(bounds);
});
new Control.geocoder({ defaultMarkGeocode: false })
.on("markgeocode", (e) => {
const { bbox, center } = e.geocode;
const poly = L.polygon([
bbox.getSouthEast(),
bbox.getNorthEast(),
bbox.getNorthWest(),
bbox.getSouthWest(),
]);
circle.setLatLng(center);
const lBox = poly.getBounds();
const cBox = circle.getBounds();
const bounds = cBox.contains(lBox) ? cBox : lBox;
map.fitBounds(bounds);
map.pm.enableGlobalEditMode();
const { lat, lng } = center;
$latitude.value = lat;
$longitude.value = lng;
})
.addTo(map);
map.fitBounds(circle.getBounds(), { animate: false });
},
};
export const Modal = {
_freeze() {
document.documentElement.classList.add("is-clipped");
},
_unfreeze() {
document.documentElement.classList.remove("is-clipped");
},
mounted() {
// assumption: 'is-active' is always added after the initial mount
},
updated() {
this.el.classList.contains("is-active") ? this._freeze() : this._unfreeze();
},
destroyed() {
this._unfreeze();
},
};
export const NumericInput = {
mounted() {
this.el.onkeypress = (evt) => {
const charCode = evt.which ? evt.which : evt.keyCode;
return !(charCode > 31 && (charCode < 48 || charCode > 57));
};
},
};