My Site Preloader
Skip to main content

La hora en México es (JS)

¿Que hora es en México en este mismo momento? Para eso aquí un gadget por si publicas en otros paises y quieres te contacten y deseas sepan de mera casualidad la hora en México.

El resultado será:

 <script id="rendered-js" type="module">
class Mexico extends HTMLElement {
	static tagName = "hr-mx";
	static prefix = "hr-mx--";
	static attr = {
		template: "data-Mexico",
		ready: "ready",
		defer: "defer-hydration"
	};

	static onceCache = new Map();
	static onReady = new Map();

	static fallback = {
		":not(hr-mx,:defined,[defer-hydration])": (readyPromise, node, prefix) => {
			// remove from document to prevent web component init
			let cloned = document.createElement(prefix + node.localName);
			for (let attr of node.getAttributeNames()) {
				cloned.setAttribute(attr, node.getAttribute(attr));
			}

			// Declarative Shadow DOM (with polyfill)
			let shadowroot = node.shadowRoot;
			if (!shadowroot) {
				let tmpl = node.querySelector(
					":scope > template:is([shadowrootmode], [shadowroot])"
				);
				if (tmpl) {
					let mode =
						tmpl.getAttribute("shadowrootmode") ||
						tmpl.getAttribute("shadowroot") ||
						"closed";
					shadowroot = node.attachShadow({ mode }); // default is closed
					shadowroot.appendChild(tmpl.content.cloneNode(true));
				}
			}

			// Cheers to https://gist.github.com/developit/45c85e9be01e8c3f1a0ec073d600d01e
			if (shadowroot) {
				cloned
					.attachShadow({ mode: shadowroot.mode })
					.append(...shadowroot.childNodes);
			}

			// Keep *same* child nodes to preserve state of children (e.g. details->summary)
			cloned.append(...node.childNodes);
			node.replaceWith(cloned);

			return readyPromise.then(() => {
				// Restore original children and shadow DOM
				if (cloned.shadowRoot) {
					node.shadowRoot.append(...cloned.shadowRoot.childNodes);
				}
				node.append(...cloned.childNodes);
				cloned.replaceWith(node);
			});
		}
	};

	constructor() {
		super();

		// Internal promises
		this.ready = new Promise((resolve) => {
			this.readyResolve = resolve;
		});
	}

	// any parents of `el` that are <hr-mx> (with conditions)
	static getParents(el, stopAt = false) {
		let nodes = [];
		while (el) {
			if (el.matches && el.matches(Mexico.tagName)) {
				if (stopAt && el === stopAt) {
					break;
				}

				if (Conditions.hasConditions(el)) {
					nodes.push(el);
				}
			}
			el = el.parentNode;
		}
		return nodes;
	}

	static async ready(el, parents) {
		if (!parents) {
			parents = Mexico.getParents(el);
		}
		if (parents.length === 0) {
			return;
		}
		let imports = await Promise.all(parents.map((p) => p.wait()));
		// return innermost module import
		if (imports.length) {
			return imports[0];
		}
	}

	forceFallback() {
		if (window.Mexico) {
			Object.assign(Mexico.fallback, window.Mexico.fallback);
		}

		for (let selector in Mexico.fallback) {
			// Reverse here as a cheap way to get the deepest nodes first
			let components = Array.from(this.querySelectorAll(selector)).reverse();

			// with thanks to https://gist.github.com/cowboy/938767
			for (let node of components) {
				if (!node.isConnected) {
					continue;
				}

				let parents = Mexico.getParents(node);
				// must be in a leaf Mexico (not nested deep)
				if (parents.length === 1) {
					let p = Mexico.ready(node, parents);
					Mexico.fallback[selector](p, node, Mexico.prefix);
				}
			}
		}
	}

	wait() {
		return this.ready;
	}

	async connectedCallback() {
		// Only use fallback content with loading conditions
		if (Conditions.hasConditions(this)) {
			// Keep fallback content without initializing the components
			this.forceFallback();
		}

		await this.hydrate();
	}

	getTemplates() {
		return this.querySelectorAll(`template[${Mexico.attr.template}]`);
	}

	replaceTemplates(templates) {
		// replace <template> with the live content
		for (let node of templates) {
			// if the template is nested inside another child <hr-mx> inside, skip
			if (Mexico.getParents(node, this).length > 0) {
				continue;
			}

			let value = node.getAttribute(Mexico.attr.template);
			// get rid of the rest of the content on the Mexico
			if (value === "replace") {
				let children = Array.from(this.childNodes);
				for (let child of children) {
					this.removeChild(child);
				}
				this.appendChild(node.content);
				break;
			} else {
				let html = node.innerHTML;
				if (value === "once" && html) {
					if (Mexico.onceCache.has(html)) {
						node.remove();
						return;
					}

					Mexico.onceCache.set(html, true);
				}

				node.replaceWith(node.content);
			}
		}
	}

	async hydrate() {
		let conditions = [];
		if (this.parentNode) {
			// wait for all parents before hydrating
			conditions.push(Mexico.ready(this.parentNode));
		}

		let attrs = Conditions.getConditions(this);
		for (let condition in attrs) {
			if (Conditions.map[condition]) {
				conditions.push(Conditions.map[condition](attrs[condition], this));
			}
		}

		// Loading conditions must finish before dependencies are loaded
		await Promise.all(conditions);

		this.replaceTemplates(this.getTemplates());

		for (let fn of Mexico.onReady.values()) {
			await fn.call(this, Mexico);
		}

		this.readyResolve();

		this.setAttribute(Mexico.attr.ready, "");

		// Remove [defer-hydration]
		this.querySelectorAll(`[${Mexico.attr.defer}]`).forEach((node) =>
			node.removeAttribute(Mexico.attr.defer)
		);
	}
}

class Conditions {
	static map = {
		visible: Conditions.visible,
		idle: Conditions.idle,
		interaction: Conditions.interaction,
		media: Conditions.media,
		"save-data": Conditions.saveData
	};

	static hasConditions(node) {
		return Object.keys(Conditions.getConditions(node)).length > 0;
	}

	static getConditions(node) {
		let map = {};
		for (let key of Object.keys(Conditions.map)) {
			if (node.hasAttribute(`on:${key}`)) {
				map[key] = node.getAttribute(`on:${key}`);
			}
		}

		return map;
	}

	static visible(noop, el) {
		if (!("IntersectionObserver" in window)) {
			// runs immediately
			return;
		}

		return new Promise((resolve) => {
			let observer = new IntersectionObserver((entries) => {
				let [entry] = entries;
				if (entry.isIntersecting) {
					observer.unobserve(entry.target);
					resolve();
				}
			});

			observer.observe(el);
		});
	}

	// Warning: on:idle is not very useful with other conditions as it may resolve long before.
	static idle() {
		let onload = new Promise((resolve) => {
			if (document.readyState !== "complete") {
				window.addEventListener("load", () => resolve(), { once: true });
			} else {
				resolve();
			}
		});

		if (!("requestIdleCallback" in window)) {
			// run immediately
			return onload;
		}

		// both idle and onload
		return Promise.all([
			new Promise((resolve) => {
				requestIdleCallback(() => {
					resolve();
				});
			}),
			onload
		]);
	}

	static interaction(eventOverrides, el) {
		let events = ["click", "touchstart"];
		// event overrides e.g. on:interaction="mouseenter"
		if (eventOverrides) {
			events = (eventOverrides || "").split(",").map((entry) => entry.trim());
		}

		return new Promise((resolve) => {
			function resolveFn(e) {
				resolve();

				// cleanup the other event handlers
				for (let name of events) {
					el.removeEventListener(name, resolveFn);
				}
			}

			for (let name of events) {
				el.addEventListener(name, resolveFn, { once: true });
			}
		});
	}

	static media(query) {
		let mm = {
			matches: true
		};

		if (query && "matchMedia" in window) {
			mm = window.matchMedia(query);
		}

		if (mm.matches) {
			return;
		}

		return new Promise((resolve) => {
			mm.addListener((e) => {
				if (e.matches) {
					resolve();
				}
			});
		});
	}

	static saveData(expects) {
		// return early if API does not exist
		if (
			!("connection" in navigator) ||
			navigator.connection.saveData === (expects !== "false")
		) {
			return;
		}

		// dangly promise
		return new Promise(() => {});
	}
}

// Should this auto define? Folks can redefine later using { component } export
if ("customElements" in window) {
	window.customElements.define(Mexico.tagName, Mexico);
	window.Mexico = Mexico;
}

export {
	Mexico,
	Mexico as component // Backwards compat only: recommend `Mexico` export
};

// TODO remove in 4.0
export const ready = Mexico.ready; // Backwards compat only: recommend `Mexico` export
    </script>
<hr-mx on:visible="">
	<template data-Mexico="">
		<local-time><span lang="en">Time in Mexico City:</span> <span id="current-live-time"></span>
		</local-time>
		<script>
			let options = {
				timeZone: 'America/Mexico_City',
				hour: 'numeric',
				minute: 'numeric',
			}
			function updateTime() {
				document.getElementById('current-live-time').textContent = (new Date()).toLocaleString([], options);
			}
			updateTime();
			window.setInterval(updateTime, 1000);
		</script>
		<script></script>
	</template>
</hr-mx>

Por cierto, sabias que en español es correcto escribir dos mil (separado, no junto) y es correcto veintidós (con tilde).


View on Instagram View on Flickr View on Twitter

Like Repost Reply