Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * @fires Event#change when checked is changed
- * @fires Event#change-mod when mod is changed
- * @fires Event#next when the mod was left-clicked or selected with enter
- * @fires Event#prev when the mod was right-clicked
- */
- export class OsuModCheckbox extends HTMLElement {
- protected wrapper: HTMLLabelElement;
- protected cb: HTMLInputElement;
- protected span: HTMLElement;
- protected shadow: ShadowRoot;
- protected css: HTMLStyleElement;
- constructor() {
- // Always call super first in constructor
- super();
- this.shadow = this.attachShadow({ mode: "open" });
- this.css = document.createElement("style");
- this.css.textContent = `
- :host {
- display: inline-block;
- max-width: calc(4.1282em * var(--icon-scale, 1));
- margin: 0 0.3em;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- }
- .mapmod:focus-within span:before {
- filter: drop-shadow(0 2px 4px white);
- }
- .mapmod {
- display: block;
- position: relative;
- z-index: 11;
- }
- .mapmod input {
- width: 0;
- height: 0;
- opacity: 0;
- position: absolute;
- left: 0;
- top: 0;
- }
- .mapmod input + span {
- display: block;
- text-align: center;
- }
- .mapmod input + span:before {
- content: "";
- display: block;
- text-align: center;
- width: calc(4.1282em * var(--icon-scale, 1));
- height: calc(2.8em * var(--icon-scale, 1));
- opacity: 0.6;
- background-image: url(/img/mod_fallback.min.svg), url(/img/modbg.min.svg);
- background-size: auto 70%, 100%;
- background-repeat: no-repeat;
- background-position: center center;
- transition: transform 0.1s ease-out, opacity 0.1s ease-out;
- z-index: -5;
- }
- .mapmod:hover input + span:before {
- opacity: 0.8;
- }
- .mapmod input:checked + span:before {
- opacity: 1;
- transform: scale(1.15) rotate(6deg);
- opacity: 1;
- }
- .mapmod.mod_ez input + span:before { background-image: url(/img/mod_ez.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_nf input + span:before { background-image: url(/img/mod_nf.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_ht input + span:before { background-image: url(/img/mod_ht.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_so input + span:before { background-image: url(/img/mod_so.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_hr input + span:before { background-image: url(/img/mod_hr.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_sd input + span:before { background-image: url(/img/mod_sd.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_dt input + span:before { background-image: url(/img/mod_dt.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_nc input + span:before { background-image: url(/img/mod_nc.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_hd input + span:before, .mapmod.mod_fi input + span:before { background-image: url(/img/mod_hd.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_fl input + span:before {background-image: url(/img/mod_fl.min.svg), url(/img/modbg.min.svg);}
- .mapmod.mod_rx input + span:before { background-image: url(/img/mod_rx.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_ap input + span:before { background-image: url(/img/mod_ap.min.svg), url(/img/modbg.min.svg); }
- .mapmod.mod_rn input + span:before { background-image: url(/img/mod_rn.min.svg), url(/img/modbg.min.svg); }
- .mapmod.hidden {
- pointer-events: none;
- opacity: 0;
- }
- @keyframes modentry {
- 0% {
- opacity: 1;
- transform: translate(7%, 17%) scale(1.15) rotate(6deg);
- transform-origin: 100% 100%;
- z-index: -10;
- filter: brightness(0.8);
- }
- 40% {
- transform: translate(7%, 17%) scale(1.15) rotate(-11deg);
- transform-origin: 100% 100%;
- z-index: -1;
- filter: brightness(0.8);
- }
- 60% {
- transform: translate(4%, 15%) scale(1.15) rotate(-11deg);
- transform-origin: 100% 100%;
- z-index: -1;
- filter: brightness(1);
- }
- 100% {
- transform: translate(4%, 15%) scale(1.15) rotate(6deg);
- transform-origin: 100% 100%;
- z-index: -5;
- }
- }
- .mapmod.multi.entry span:before {
- animation: 0.2s modentry linear;
- }
- .mapmod.multi.entry.reverse span:before {
- animation: 0.2s modentry linear reverse;
- }
- @keyframes modexit {
- 0% {
- opacity: 1;
- transform: translate(7%, 17%) scale(1.15) rotate(6deg);
- transform-origin: 100% 100%;
- filter: brightness(1);
- }
- 40% {
- transform: translate(7%, 17%) scale(1.15) rotate(17deg);
- transform-origin: 100% 100%;
- filter: brightness(1);
- }
- 60% {
- transform: translate(4%, 15%) scale(1.15) rotate(17deg);
- transform-origin: 100% 100%;
- filter: brightness(0.8);
- }
- 100% {
- opacity: 1;
- transform: translate(4%, 15%) scale(1.15) rotate(6deg);
- transform-origin: 100% 100%;
- filter: brightness(0.8);
- }
- }
- @keyframes opacityexit {
- from { opacity: 1; }
- to { opacity: 0; }
- }
- .mapmod.multi.exit.hidden {
- animation: 0.2s opacityexit step-end;
- color: transparent;
- }
- .mapmod.multi.exit span:before {
- animation: 0.2s modexit linear;
- }
- .mapmod.multi.exit.reverse span:before {
- animation: 0.2s modexit linear reverse;
- }
- `;
- // attach the created elements to the shadow dom
- this.shadow.appendChild(this.css);
- this.wrapper = document.createElement("label");
- this.wrapper.classList.add("mapmod", "checkbox");
- this.shadow.appendChild(this.wrapper);
- this.cb = document.createElement("input");
- this.cb.setAttribute("type", "checkbox");
- this.cb.setAttribute("aria-label", "Mod");
- this.cb.onchange = () => {
- this.checked = this.cb.checked;
- this.dispatchEvent(new CustomEvent("next", {
- bubbles: true,
- cancelable: false
- }));
- if (this.wrapper.classList.contains("reverse"))
- this.wrapper.classList.remove("reverse");
- };
- this.wrapper.appendChild(this.cb);
- this.span = document.createElement("span");
- this.wrapper.appendChild(this.span);
- this.oncontextmenu = (e) => {
- e.preventDefault();
- this.checked = !this.checked;
- this.dispatchEvent(new CustomEvent("prev", {
- bubbles: true,
- cancelable: false
- }));
- if (!this.wrapper.classList.contains("reverse"))
- this.wrapper.classList.add("reverse");
- };
- }
- toggle() {
- this.checked = !this.checked;
- }
- static get observedAttributes() { return ["mod", "checked", "multi", "data-hidden"]; }
- attributeChangedCallback(name: string, oldValue: string, newValue: string) {
- switch (name) {
- case "mod":
- if (oldValue)
- this.wrapper.classList.remove("mod_" + oldValue.toLowerCase());
- this.wrapper.classList.add("mod_" + newValue.toLowerCase());
- this.span.textContent = newValue;
- this.cb.setAttribute("aria-label", "Mod " + newValue);
- this.dispatchEvent(new CustomEvent("change-mod", {
- bubbles: true,
- cancelable: false
- }));
- break;
- case "checked":
- if (this.cb.checked != this.checked)
- this.cb.checked = this.checked;
- this.dispatchEvent(new CustomEvent("change", {
- bubbles: true,
- cancelable: false
- }));
- break;
- case "multi":
- if (newValue) {
- this.wrapper.classList.add("multi");
- this.wrapper.classList.remove("single");
- }
- else {
- this.wrapper.classList.remove("multi");
- this.wrapper.classList.add("single");
- }
- break;
- case "data-hidden":
- if (newValue) {
- this.wrapper.classList.add("hidden");
- this.wrapper.classList.remove("entry");
- if (this.checked)
- this.wrapper.classList.add("exit");
- this.cb.setAttribute("tabindex", "-1");
- this.cb.setAttribute("readonly", "readonly");
- }
- else {
- this.wrapper.classList.remove("hidden");
- this.wrapper.classList.remove("exit");
- if (this.checked)
- this.wrapper.classList.add("entry");
- this.cb.removeAttribute("tabindex");
- this.cb.removeAttribute("readonly");
- this.cb.focus();
- }
- break;
- default:
- console.warn("unknown property change", name, oldValue, newValue);
- break;
- }
- }
- get checked(): boolean { return !!this.getAttribute("checked"); }
- set checked(checked: boolean) { checked ? this.setAttribute("checked", "checked") : this.removeAttribute("checked"); }
- /**
- * Turns on fancy flip on/off animations when hiding/showing
- */
- get multi(): boolean { return !!this.getAttribute("multi"); }
- set multi(multi: boolean) { multi ? this.setAttribute("multi", "multi") : this.removeAttribute("multi"); }
- /**
- * Plays a hide/show animation
- */
- get hidden(): boolean { return !!this.getAttribute("data-hidden"); }
- set hidden(hidden: boolean) { hidden ? this.setAttribute("data-hidden", "data-hidden") : this.removeAttribute("data-hidden"); }
- get mod(): string { return this.getAttribute("mod") || ""; }
- set mod(mod: string) { this.setAttribute("mod", mod || ""); }
- get value(): string | null { return this.checked ? this.mod : null; }
- }
- window.customElements.define("osu-mod-checkbox", OsuModCheckbox);
- export class OsuModsButton extends HTMLElement {
- mods: OsuModCheckbox[];
- css: HTMLStyleElement;
- shadow: ShadowRoot;
- constructor() {
- // Always call super first in constructor
- super();
- this.shadow = this.attachShadow({ mode: "open" });
- this.css = document.createElement("style");
- this.css.textContent = `
- :host {
- display: inline-block;
- position: relative;
- width: calc(4.2em * var(--icon-scale, 1));
- height: calc(2.8em * var(--icon-scale, 1) + 1.5em);
- }
- osu-mod-checkbox {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 10;
- transition: z-index 0.2s linear;
- }
- osu-mod-checkbox[data-hidden] {
- pointer-events: none;
- z-index: 0;
- }
- `;
- // attach the created elements to the shadow dom
- this.shadow.appendChild(this.css);
- this.mods = [];
- }
- static get observedAttributes() { return ["modset"]; }
- attributeChangedCallback(name: string, oldValue: string, newValue: string) {
- switch (name) {
- case "modset":
- var newMods = newValue.split(/\s+/g);
- while (this.mods.length < newMods.length) {
- var cb = <OsuModCheckbox>document.createElement("osu-mod-checkbox");
- this.mods.push(cb);
- this.shadow.appendChild(cb);
- cb.addEventListener("next", () => this.next());
- cb.addEventListener("prev", () => this.prev());
- }
- while (this.mods.length > newMods.length) {
- this.shadow.removeChild(<any>this.mods.pop());
- }
- for (let index = 0; index < newMods.length; index++) {
- this.mods[index].checked = false;
- this.mods[index].mod = newMods[index];
- this.mods[index].hidden = true;
- this.mods[index].multi = true;
- }
- this.mods[0].hidden = false;
- break;
- default:
- console.warn("unknown property change", name, oldValue, newValue);
- break;
- }
- }
- get index(): number {
- for (let i = 0; i < this.mods.length; i++) {
- if (!this.mods[i].hidden)
- return i;
- }
- return 0;
- }
- get value(): string | null {
- return this.mods[this.index].checked ? this.mods[this.index].mod : null;
- }
- next() {
- let i = this.index;
- let j = (i + 1) % this.mods.length;
- if (!this.mods[i].checked) {
- this.mods[i].checked = true;
- this.mods[i].hidden = true;
- this.mods[i].checked = false;
- this.mods[j].checked = true;
- this.mods[j].hidden = false;
- this.mods[j].checked = j != 0;
- }
- this.dispatchEvent(new CustomEvent("change", {
- bubbles: true,
- cancelable: false
- }));
- }
- prev() {
- let i = this.index;
- let j = (i + this.mods.length - 1) % this.mods.length;
- if (i != 0 || this.mods[i].checked) {
- this.mods[i].checked = true;
- this.mods[i].hidden = true;
- this.mods[i].checked = false;
- this.mods[j].checked = true;
- this.mods[j].hidden = false;
- }
- this.dispatchEvent(new CustomEvent("change", {
- bubbles: true,
- cancelable: false
- }));
- }
- }
- window.customElements.define("osu-mods-button", OsuModsButton);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement