826 lines
31 KiB
TypeScript
826 lines
31 KiB
TypeScript
|
|
/**
|
||
|
|
----------------------- [ MenuV ] -----------------------
|
||
|
|
-- GitHub: https://github.com/ThymonA/menuv/
|
||
|
|
-- License: GNU General Public License v3.0
|
||
|
|
-- https://choosealicense.com/licenses/gpl-3.0/
|
||
|
|
-- Author: Thymon Arens <contact@arens.io>
|
||
|
|
-- Name: MenuV
|
||
|
|
-- Version: 1.0.0
|
||
|
|
-- Description: FiveM menu library for creating menu's
|
||
|
|
----------------------- [ MenuV ] -----------------------
|
||
|
|
*/
|
||
|
|
import VUE from 'vue';
|
||
|
|
import STYLE from './vue_components/style';
|
||
|
|
import * as VueScrollTo from 'vue-scrollto';
|
||
|
|
|
||
|
|
VUE.use(VueScrollTo.default, {
|
||
|
|
container: 'ul.menuv-items',
|
||
|
|
duration: 500,
|
||
|
|
easing: 'ease-in',
|
||
|
|
offset: -25,
|
||
|
|
force: true,
|
||
|
|
cancelable: false,
|
||
|
|
onStart: false,
|
||
|
|
onDone: false,
|
||
|
|
onCancel: false,
|
||
|
|
x: false,
|
||
|
|
y: true
|
||
|
|
});
|
||
|
|
|
||
|
|
export interface Sounds {
|
||
|
|
type: 'native' | 'custom';
|
||
|
|
name: string;
|
||
|
|
library: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Option {
|
||
|
|
label: string;
|
||
|
|
description: string;
|
||
|
|
value: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Item {
|
||
|
|
index: number;
|
||
|
|
type: 'button' | 'menu' | 'checkbox' | 'confirm' | 'range' | 'slider' | 'label' | 'unknown';
|
||
|
|
uuid: string;
|
||
|
|
icon: string;
|
||
|
|
label: string;
|
||
|
|
description: string;
|
||
|
|
value: any;
|
||
|
|
prev_value: any;
|
||
|
|
values: Option[];
|
||
|
|
min: number;
|
||
|
|
max: number;
|
||
|
|
disabled: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Menu {
|
||
|
|
hidden: boolean;
|
||
|
|
theme: 'default' | 'native';
|
||
|
|
resource: string;
|
||
|
|
uuid: string;
|
||
|
|
title: string;
|
||
|
|
subtitle: string;
|
||
|
|
position: 'topleft' | 'topcenter' | 'topright' | 'centerleft' | 'center' | 'centerright' | 'bottomleft' | 'bottomcenter' | 'bottomright';
|
||
|
|
size: 'size-100' | 'size-110' | 'size-125' | 'size-150' | 'size-175' | 'size-200';
|
||
|
|
color: {
|
||
|
|
r: number,
|
||
|
|
g: number,
|
||
|
|
b: number
|
||
|
|
};
|
||
|
|
items: Item[];
|
||
|
|
texture: string;
|
||
|
|
dictionary: string;
|
||
|
|
defaultSounds: Record<'UP' | 'DOWN' | 'LEFT' | 'RIGHT' | 'ENTER' | 'CLOSE', Sounds>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export default VUE.extend({
|
||
|
|
template: '#menuv_template',
|
||
|
|
name: 'menuv',
|
||
|
|
components: {
|
||
|
|
STYLE
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
theme: 'default',
|
||
|
|
resource: 'menuv',
|
||
|
|
uuid: '',
|
||
|
|
menu: false,
|
||
|
|
show: false,
|
||
|
|
title: 'MenuV',
|
||
|
|
subtitle: '',
|
||
|
|
position: 'topleft',
|
||
|
|
size: 'size-110',
|
||
|
|
texture: 'none',
|
||
|
|
dictionary: 'none',
|
||
|
|
color: {
|
||
|
|
r: 0,
|
||
|
|
g: 0,
|
||
|
|
b: 255
|
||
|
|
},
|
||
|
|
items: [] as Item[],
|
||
|
|
listener: (event: MessageEvent) => {},
|
||
|
|
index: 0,
|
||
|
|
sounds: {} as Record<'UP' | 'DOWN' | 'LEFT' | 'RIGHT' | 'ENTER' | 'CLOSE', Sounds>,
|
||
|
|
cached_indexes: {} as Record<string, number>
|
||
|
|
}
|
||
|
|
},
|
||
|
|
destroyed() {
|
||
|
|
window.removeEventListener('message', this.listener)
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
this.listener = (event: MessageEvent) => {
|
||
|
|
const data: any = event.data ||(<any>event).detail;
|
||
|
|
|
||
|
|
if (!data || !data.action) { return; }
|
||
|
|
|
||
|
|
const typeRef = data.action as 'UPDATE_STATUS' | 'OPEN_MENU' | 'CLOSE_MENU' | 'UPDATE_TITLE' | 'UPDATE_SUBTITLE' | 'KEY_PRESSED' | 'RESOURCE_STOPPED' | 'UPDATE_ITEMS' | 'UPDATE_ITEM' | 'REFRESH_MENU'
|
||
|
|
|
||
|
|
if (this[typeRef]) {
|
||
|
|
this[typeRef](data);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
window.addEventListener('message', this.listener);
|
||
|
|
|
||
|
|
this.POST('https://menuv/loaded', {});
|
||
|
|
},
|
||
|
|
watch: {
|
||
|
|
theme() {},
|
||
|
|
title() {},
|
||
|
|
subtitle() {},
|
||
|
|
position() {},
|
||
|
|
color() {},
|
||
|
|
options() {},
|
||
|
|
menu() {},
|
||
|
|
show() {},
|
||
|
|
size() {},
|
||
|
|
index(newValue, oldValue) {
|
||
|
|
let prev_uuid = null;
|
||
|
|
let next_uuid = null;
|
||
|
|
|
||
|
|
if (oldValue >= 0 && oldValue < this.items.length) {
|
||
|
|
prev_uuid = this.items[oldValue].uuid;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (newValue >= 0 && newValue < this.items.length) {
|
||
|
|
next_uuid = this.items[newValue].uuid;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.cached_indexes[this.uuid] = newValue;
|
||
|
|
this.POST(`https://menuv/switch`, { prev: prev_uuid, next: next_uuid, r: this.resource });
|
||
|
|
},
|
||
|
|
items: {
|
||
|
|
deep: true,
|
||
|
|
handler(newValue: Item[], oldValue: Item[]) {
|
||
|
|
if (this.index >= newValue.length || this.index < 0) { return; }
|
||
|
|
|
||
|
|
let sameItem = null;
|
||
|
|
const currentItem = newValue[this.index];
|
||
|
|
|
||
|
|
if (currentItem == null) { return; }
|
||
|
|
|
||
|
|
for (var i = 0; i < oldValue.length; i++) {
|
||
|
|
if (currentItem.uuid == oldValue[i].uuid) {
|
||
|
|
sameItem = oldValue[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (sameItem == null || currentItem.value == currentItem.prev_value) { return; }
|
||
|
|
|
||
|
|
currentItem.prev_value = currentItem.value;
|
||
|
|
|
||
|
|
this.POST(`https://menuv/update`, { uuid: currentItem.uuid, prev: sameItem.value, now: currentItem.value, r: this.resource });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
updated: function() {
|
||
|
|
if (this.index < 0) { return; }
|
||
|
|
|
||
|
|
const el = document.getElementsByTagName('li');
|
||
|
|
|
||
|
|
for (var i = 0; i < el.length; i++) {
|
||
|
|
const index = el[i].getAttribute('index')
|
||
|
|
|
||
|
|
if (index === null) { continue; }
|
||
|
|
|
||
|
|
const idx = parseInt(index);
|
||
|
|
|
||
|
|
if (idx == this.index) {
|
||
|
|
this.$scrollTo(`li[index="${this.index}"]`, 0, {});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
computed: {},
|
||
|
|
methods: {
|
||
|
|
UPDATE_STATUS({ status }: { status: boolean }) {
|
||
|
|
if (this.menu) { this.show = status; }
|
||
|
|
},
|
||
|
|
OPEN_MENU({ menu, reopen }: { menu: Menu, reopen: boolean }) {
|
||
|
|
this.POST(`https://menuv/open`, { uuid: this.uuid, new_uuid: menu.uuid, r: this.resource });
|
||
|
|
this.RESET_MENU();
|
||
|
|
|
||
|
|
this.theme = this.ENSURE(menu.theme, 'default');
|
||
|
|
this.resource = this.ENSURE(menu.resource, 'menuv');
|
||
|
|
this.uuid = this.ENSURE(menu.uuid, '00000000-0000-0000-0000-000000000000');
|
||
|
|
this.title = this.ENSURE(menu.title, this.title);
|
||
|
|
this.subtitle = this.ENSURE(menu.subtitle, this.subtitle);
|
||
|
|
this.position = this.ENSURE(menu.position, 'topleft');
|
||
|
|
this.size = this.ENSURE(menu.size, 'size-110');
|
||
|
|
this.texture = this.ENSURE(menu.texture, 'none');
|
||
|
|
this.dictionary = this.ENSURE(menu.dictionary, 'none');
|
||
|
|
this.color = menu.color || this.color;
|
||
|
|
this.sounds = menu.defaultSounds || this.sounds;
|
||
|
|
this.show = !(menu.hidden || false);
|
||
|
|
this.menu = true;
|
||
|
|
|
||
|
|
const _items = this.items = menu.items || [];
|
||
|
|
|
||
|
|
for (var i = 0; i < _items.length; i++) {
|
||
|
|
_items[i].prev_value = _items[i].value;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.items = _items.sort((item1, item2) => {
|
||
|
|
if (item1.index > item2.index) { return 1; }
|
||
|
|
if (item1.index < item2.index) { return -1; }
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
});
|
||
|
|
|
||
|
|
const index = (reopen || false) ? (this.cached_indexes[this.uuid] || 0) : 0;
|
||
|
|
const nextIndex = this.NEXT_INDEX(index);
|
||
|
|
const prevIndex = this.PREV_INDEX(nextIndex);
|
||
|
|
|
||
|
|
this.index = prevIndex;
|
||
|
|
this.cached_indexes[this.uuid] = prevIndex;
|
||
|
|
this.POST(`https://menuv/opened`, { uuid: this.uuid, r: this.resource });
|
||
|
|
},
|
||
|
|
REFRESH_MENU({ menu }: { menu: Menu }) {
|
||
|
|
const current_index = this.index + 0;
|
||
|
|
|
||
|
|
this.RESET_MENU();
|
||
|
|
|
||
|
|
this.theme = this.ENSURE(menu.theme, 'default');
|
||
|
|
this.resource = this.ENSURE(menu.resource, 'menuv');
|
||
|
|
this.uuid = this.ENSURE(menu.uuid, '00000000-0000-0000-0000-000000000000');
|
||
|
|
this.title = this.ENSURE(menu.title, this.title);
|
||
|
|
this.subtitle = this.ENSURE(menu.subtitle, this.subtitle);
|
||
|
|
this.position = this.ENSURE(menu.position, 'topleft');
|
||
|
|
this.size = this.ENSURE(menu.size, 'size-110');
|
||
|
|
this.texture = this.ENSURE(menu.texture, 'none');
|
||
|
|
this.dictionary = this.ENSURE(menu.dictionary, 'none');
|
||
|
|
this.color = menu.color || this.color;
|
||
|
|
this.sounds = menu.defaultSounds || this.sounds;
|
||
|
|
this.show = !(menu.hidden || false);
|
||
|
|
this.menu = true;
|
||
|
|
|
||
|
|
const _items = this.items = menu.items || [];
|
||
|
|
|
||
|
|
for (var i = 0; i < _items.length; i++) {
|
||
|
|
_items[i].prev_value = _items[i].value;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.items = this.items = _items.sort((item1, item2) => {
|
||
|
|
if (item1.index > item2.index) { return 1; }
|
||
|
|
if (item1.index < item2.index) { return -1; }
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
});
|
||
|
|
|
||
|
|
const nextIndex = this.NEXT_INDEX(current_index);
|
||
|
|
const prevIndex = this.PREV_INDEX(nextIndex);
|
||
|
|
|
||
|
|
this.index = prevIndex;
|
||
|
|
},
|
||
|
|
CLOSE_MENU({ uuid }: { uuid: string }) {
|
||
|
|
if (this.uuid == uuid) {
|
||
|
|
this.RESET_MENU();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
UPDATE_TITLE({ title, __uuid }: { title: string, __uuid: string }) {
|
||
|
|
if (__uuid != this.uuid) { return; }
|
||
|
|
|
||
|
|
this.title = title || this.title;
|
||
|
|
},
|
||
|
|
UPDATE_SUBTITLE({ subtitle, __uuid }: { subtitle: string, __uuid: string }) {
|
||
|
|
if (__uuid != this.uuid) { return; }
|
||
|
|
|
||
|
|
this.subtitle = subtitle || this.subtitle;
|
||
|
|
},
|
||
|
|
UPDATE_ITEMS({ items, __uuid }: { items: Item[], __uuid: string }) {
|
||
|
|
if (__uuid != this.uuid) { return; }
|
||
|
|
|
||
|
|
const _items = items || this.items;
|
||
|
|
|
||
|
|
for (var i = 0; i < _items.length; i++) {
|
||
|
|
_items[i].prev_value = _items[i].value;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.items = _items;
|
||
|
|
|
||
|
|
const nextIndex = this.NEXT_INDEX(this.index);
|
||
|
|
const prevIndex = this.PREV_INDEX(nextIndex);
|
||
|
|
|
||
|
|
this.index = prevIndex;
|
||
|
|
},
|
||
|
|
UPDATE_ITEM({ item, __uuid }: { item: Item, __uuid: string }) {
|
||
|
|
if (__uuid != this.uuid || item == null || typeof item == "undefined") { return; }
|
||
|
|
|
||
|
|
for (var i = 0; i < this.items.length; i++) {
|
||
|
|
if (this.items[i].uuid == item.uuid) {
|
||
|
|
this.items[i].icon = item.icon || this.items[i].icon;
|
||
|
|
this.items[i].label = item.label || this.items[i].label;
|
||
|
|
this.items[i].description = item.description || this.items[i].description;
|
||
|
|
this.items[i].value = item.value || this.items[i].value;
|
||
|
|
this.items[i].values = item.values || this.items[i].values;
|
||
|
|
this.items[i].min = item.min || this.items[i].min;
|
||
|
|
this.items[i].max = item.max || this.items[i].max;
|
||
|
|
this.items[i].disabled = item.disabled || this.items[i].disabled;
|
||
|
|
|
||
|
|
if ((this.index == i && this.items[i].disabled) || (this.index < 0 && !this.items[i].disabled)) {
|
||
|
|
this.index = this.NEXT_INDEX(this.index);
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
ADD_ITEM({ item, index, __uuid }: { item: Item, index?: number, __uuid: string }) {
|
||
|
|
if (__uuid != this.uuid) { return; }
|
||
|
|
|
||
|
|
item.prev_value = item.value;
|
||
|
|
|
||
|
|
for (var i = 0; i < this.items.length; i++) {
|
||
|
|
if (this.items[i].uuid == item.uuid) {
|
||
|
|
this.UPDATE_ITEM({ item: item, __uuid: __uuid });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const _items = this.items;
|
||
|
|
|
||
|
|
if (typeof index == 'undefined' || index == null || index < 0 || index >= _items.length) {
|
||
|
|
_items.push(item);
|
||
|
|
} else {
|
||
|
|
_items.splice(index, 0, item);
|
||
|
|
}
|
||
|
|
|
||
|
|
this.items = _items.sort((item1, item2) => {
|
||
|
|
if (item1.index > item2.index) { return 1; }
|
||
|
|
if (item1.index < item2.index) { return -1; }
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
});
|
||
|
|
|
||
|
|
if (this.index < 0 && !item.disabled) { this.index = this.NEXT_INDEX(this.index); }
|
||
|
|
},
|
||
|
|
REMOVE_ITEM({ uuid, __uuid }: { uuid: string, __uuid: string }) {
|
||
|
|
if (__uuid != this.uuid || typeof uuid != 'string' || uuid == '') { return }
|
||
|
|
|
||
|
|
const _items = this.items;
|
||
|
|
|
||
|
|
for (var i = 0; i < _items.length; i++) {
|
||
|
|
if (_items[i].uuid == uuid) {
|
||
|
|
_items.splice(i, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i == this.index) {
|
||
|
|
this.index = this.PREV_INDEX(this.index);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this.items = _items.sort((item1, item2) => {
|
||
|
|
if (item1.index > item2.index) { return 1; }
|
||
|
|
if (item1.index < item2.index) { return -1; }
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
});
|
||
|
|
},
|
||
|
|
RESET_MENU() {
|
||
|
|
this.theme = 'default'
|
||
|
|
this.resource = 'menuv';
|
||
|
|
this.menu = false;
|
||
|
|
this.show = false;
|
||
|
|
this.uuid = '00000000-0000-0000-0000-000000000000';
|
||
|
|
this.title = 'MenuV';
|
||
|
|
this.subtitle = '';
|
||
|
|
this.position = 'topleft';
|
||
|
|
this.size = 'size-110';
|
||
|
|
this.texture = 'none';
|
||
|
|
this.dictionary = 'none';
|
||
|
|
this.color.r = 0;
|
||
|
|
this.color.g = 0;
|
||
|
|
this.color.b = 255;
|
||
|
|
this.items = [];
|
||
|
|
this.sounds['UP'] = { type: 'custom', name: 'unknown', library: 'unknown' } as Sounds;
|
||
|
|
this.sounds['DOWN'] = { type: 'custom', name: 'unknown', library: 'unknown' } as Sounds;
|
||
|
|
this.sounds['LEFT'] = { type: 'custom', name: 'unknown', library: 'unknown' } as Sounds;
|
||
|
|
this.sounds['RIGHT'] = { type: 'custom', name: 'unknown', library: 'unknown' } as Sounds;
|
||
|
|
this.sounds['ENTER'] = { type: 'custom', name: 'unknown', library: 'unknown' } as Sounds;
|
||
|
|
this.sounds['CLOSE'] = { type: 'custom', name: 'unknown', library: 'unknown' } as Sounds;
|
||
|
|
},
|
||
|
|
GET_SLIDER_LABEL({ uuid }: { uuid: string }) {
|
||
|
|
for (var i = 0; i < this.items.length; i++) {
|
||
|
|
if (this.items[i].uuid == uuid && this.items[i].type == 'slider') {
|
||
|
|
const currentValue = this.items[i].value as number;
|
||
|
|
const values = this.items[i].values;
|
||
|
|
|
||
|
|
if (values.length == 0) { return ''; }
|
||
|
|
|
||
|
|
if (currentValue < 0 || currentValue >= values.length) {
|
||
|
|
return this.FORMAT_TEXT(values[0].label || 'Unknown');
|
||
|
|
}
|
||
|
|
|
||
|
|
return this.FORMAT_TEXT(values[currentValue].label || 'Unknown');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return '';
|
||
|
|
},
|
||
|
|
GET_CURRENT_DESCRIPTION() {
|
||
|
|
const index = this.index || 0;
|
||
|
|
|
||
|
|
if (index >= 0 && index < this.items.length) {
|
||
|
|
return this.FORMAT_TEXT(this.NL2BR(this.ENSURE(this.items[index].description, ''), true, false));
|
||
|
|
}
|
||
|
|
|
||
|
|
return '';
|
||
|
|
},
|
||
|
|
ENSURE: function<T>(input: any, output: T): T {
|
||
|
|
const inputType = typeof input;
|
||
|
|
const outputType = typeof output;
|
||
|
|
|
||
|
|
if (inputType == 'undefined') { return output as T; }
|
||
|
|
|
||
|
|
if (outputType == 'string') {
|
||
|
|
if (inputType == 'string') {
|
||
|
|
const isEmpty = input == null || (input as string) == 'nil' || (input as string) == '';
|
||
|
|
|
||
|
|
if (isEmpty) { return output as T; }
|
||
|
|
|
||
|
|
return input as T;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (inputType == 'number') { return (input as number).toString() as unknown as T || output as T; }
|
||
|
|
|
||
|
|
return output as T;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (outputType == 'number') {
|
||
|
|
if (inputType == 'string') {
|
||
|
|
const isEmpty = input == null || (input as string) == 'nil' || (input as string) == '';
|
||
|
|
|
||
|
|
if (isEmpty) { return output as T; }
|
||
|
|
|
||
|
|
return Number(input as string) as unknown as T || output as T;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (inputType == 'number') { return input as T; }
|
||
|
|
|
||
|
|
return output as T;
|
||
|
|
}
|
||
|
|
|
||
|
|
return output as T;
|
||
|
|
},
|
||
|
|
TEXT_COLOR: function(r: number, g: number, b: number, o: number): string {
|
||
|
|
o = o || 1.0
|
||
|
|
|
||
|
|
if (o > 1.0) { o = 1.0; }
|
||
|
|
if (o < 0.0) { o = 0.0; }
|
||
|
|
|
||
|
|
const luminance = ( 0.299 * r + 0.587 * g + 0.114 * b)/255;
|
||
|
|
|
||
|
|
if (luminance > 0.5) {
|
||
|
|
return `rgba(0, 0, 0, ${o})`;
|
||
|
|
}
|
||
|
|
|
||
|
|
return `rgba(255, 255, 255, ${o})`;
|
||
|
|
},
|
||
|
|
IS_DEFAULT: function(input: any): boolean {
|
||
|
|
if (typeof input == 'string') {
|
||
|
|
return input == null || (input as string) == 'nil' || (input as string) == '';
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeof input == 'number') {
|
||
|
|
return (input as number) == 0
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeof input == 'boolean') {
|
||
|
|
return (input as boolean) == false
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
},
|
||
|
|
KEY_PRESSED({ key }: { key: string }) {
|
||
|
|
if (!this.menu || !this.show) { return; }
|
||
|
|
|
||
|
|
const k = key as 'UP' | 'DOWN' | 'LEFT' | 'RIGHT' | 'ENTER' | 'CLOSE'
|
||
|
|
|
||
|
|
if (typeof k == 'undefined' || k == null) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const keyRef = `KEY_${k}` as 'KEY_UP' | 'KEY_DOWN' | 'KEY_LEFT' | 'KEY_RIGHT' | 'KEY_ENTER' | 'KEY_CLOSE' | 'KEY_CLOSE_ALL';
|
||
|
|
|
||
|
|
if (this[keyRef]) {
|
||
|
|
this[keyRef]();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
RESOURCE_STOPPED({ resource }: { resource: string }) {
|
||
|
|
if (!this.menu) { return; }
|
||
|
|
|
||
|
|
if (this.resource == resource) {
|
||
|
|
this.RESET_MENU();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
KEY_UP: function() {
|
||
|
|
const newIndex = this.PREV_INDEX(this.index);
|
||
|
|
|
||
|
|
if (this.index != newIndex) {
|
||
|
|
this.index = newIndex;
|
||
|
|
|
||
|
|
if (this.sounds['UP'] && this.sounds['UP'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'UP' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
KEY_DOWN: function() {
|
||
|
|
const newIndex = this.NEXT_INDEX(this.index);
|
||
|
|
|
||
|
|
if (this.index != newIndex) {
|
||
|
|
this.index = newIndex;
|
||
|
|
|
||
|
|
if (this.sounds['DOWN'] && this.sounds['DOWN'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'DOWN' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
KEY_LEFT: function() {
|
||
|
|
if (this.index < 0 || this.items.length <= this.index || this.items[this.index].disabled) { return; }
|
||
|
|
|
||
|
|
const item = this.items[this.index];
|
||
|
|
|
||
|
|
if (item.type == 'button' || item.type == 'menu' || item.type == 'label' || item.type == 'unknown') { return; }
|
||
|
|
|
||
|
|
switch(item.type) {
|
||
|
|
case 'confirm':
|
||
|
|
case 'checkbox':
|
||
|
|
const boolean_value = item.value as boolean;
|
||
|
|
|
||
|
|
this.items[this.index].value = !boolean_value;
|
||
|
|
|
||
|
|
if (this.sounds['LEFT'] && this.sounds['LEFT'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'LEFT' });
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
case 'range':
|
||
|
|
let new_range_index = null;
|
||
|
|
let range_value = item.value as number;
|
||
|
|
|
||
|
|
if ((range_value - 1) <= item.min) { new_range_index = item.min; }
|
||
|
|
else if ((range_value - 1) >= item.max) { new_range_index = item.max; }
|
||
|
|
else { new_range_index = (this.items[this.index].value - 1); }
|
||
|
|
|
||
|
|
if (new_range_index != this.items[this.index].value) {
|
||
|
|
this.items[this.index].value = new_range_index;
|
||
|
|
|
||
|
|
if (this.sounds['LEFT'] && this.sounds['LEFT'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'LEFT' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
case 'slider':
|
||
|
|
let new_slider_index = null;
|
||
|
|
const slider_value = item.value as number;
|
||
|
|
const slider_values = item.values || [];
|
||
|
|
|
||
|
|
if (slider_values.length <= 0) { return; }
|
||
|
|
if ((slider_value - 1) < 0 || (slider_value - 1) >= slider_values.length) { new_slider_index = (slider_values.length - 1); }
|
||
|
|
else { new_slider_index = (this.items[this.index].value - 1); }
|
||
|
|
|
||
|
|
if (new_slider_index != this.items[this.index].value) {
|
||
|
|
this.items[this.index].value = new_slider_index;
|
||
|
|
|
||
|
|
if (this.sounds['LEFT'] && this.sounds['LEFT'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'LEFT' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
KEY_RIGHT: function() {
|
||
|
|
if (this.index < 0 || this.items.length <= this.index || this.items[this.index].disabled) { return; }
|
||
|
|
|
||
|
|
const item = this.items[this.index];
|
||
|
|
|
||
|
|
if (item.type == 'button' || item.type == 'menu' || item.type == 'label' || item.type == 'unknown') { return; }
|
||
|
|
|
||
|
|
switch(item.type) {
|
||
|
|
case 'confirm':
|
||
|
|
case 'checkbox':
|
||
|
|
const boolean_value = item.value as boolean;
|
||
|
|
|
||
|
|
this.items[this.index].value = !boolean_value;
|
||
|
|
|
||
|
|
if (this.sounds['RIGHT'] && this.sounds['RIGHT'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'RIGHT' });
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
case 'range':
|
||
|
|
let new_range_index = null;
|
||
|
|
let range_value = item.value as number;
|
||
|
|
|
||
|
|
if ((range_value + 1) <= item.min) { new_range_index = item.min; }
|
||
|
|
else if ((range_value + 1) >= item.max) { new_range_index = item.max; }
|
||
|
|
else { new_range_index = (this.items[this.index].value + 1); }
|
||
|
|
|
||
|
|
if (new_range_index != this.items[this.index].value) {
|
||
|
|
this.items[this.index].value = new_range_index;
|
||
|
|
|
||
|
|
if (this.sounds['RIGHT'] && this.sounds['RIGHT'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'RIGHT' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
case 'slider':
|
||
|
|
let new_slider_index = null;
|
||
|
|
const slider_value = item.value as number;
|
||
|
|
const slider_values = item.values || [];
|
||
|
|
|
||
|
|
if (slider_values.length <= 0) { return; }
|
||
|
|
if ((slider_value + 1) < 0 || (slider_value + 1) >= slider_values.length) { new_slider_index = 0; }
|
||
|
|
else { new_slider_index = (this.items[this.index].value + 1); }
|
||
|
|
|
||
|
|
if (new_slider_index != this.items[this.index].value) {
|
||
|
|
this.items[this.index].value = new_slider_index;
|
||
|
|
|
||
|
|
if (this.sounds['RIGHT'] && this.sounds['RIGHT'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'RIGHT' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
KEY_ENTER: function() {
|
||
|
|
if (this.index < 0 || this.items.length <= this.index || this.items[this.index].disabled) { return; }
|
||
|
|
|
||
|
|
if (this.sounds['ENTER'] && this.sounds['ENTER'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'ENTER' });
|
||
|
|
}
|
||
|
|
|
||
|
|
const item = this.items[this.index];
|
||
|
|
|
||
|
|
switch(item.type) {
|
||
|
|
case 'button':
|
||
|
|
case 'menu':
|
||
|
|
this.POST(`https://menuv/submit`, { uuid: item.uuid, value: null, r: this.resource });
|
||
|
|
break;
|
||
|
|
case 'confirm':
|
||
|
|
this.POST(`https://menuv/submit`, { uuid: item.uuid, value: item.value as boolean, r: this.resource });
|
||
|
|
break;
|
||
|
|
case 'range':
|
||
|
|
let range_value = item.value as number;
|
||
|
|
|
||
|
|
if (range_value <= item.min) { range_value = item.min; }
|
||
|
|
else if (range_value >= item.max) { range_value = item.max; }
|
||
|
|
|
||
|
|
this.POST(`https://menuv/submit`, { uuid: item.uuid, value: range_value, r: this.resource });
|
||
|
|
break;
|
||
|
|
case 'checkbox':
|
||
|
|
const boolean_value = item.value as boolean;
|
||
|
|
|
||
|
|
this.items[this.index].value = !boolean_value;
|
||
|
|
|
||
|
|
this.POST(`https://menuv/submit`, { uuid: item.uuid, value: this.items[this.index].value, r: this.resource });
|
||
|
|
break;
|
||
|
|
case 'slider':
|
||
|
|
let slider_value = item.value as number;
|
||
|
|
const slider_values = item.values || [];
|
||
|
|
|
||
|
|
if (slider_values.length <= 0 || slider_value < 0 || slider_value >= slider_values.length) { return; }
|
||
|
|
|
||
|
|
this.POST(`https://menuv/submit`, { uuid: item.uuid, value: slider_value, r: this.resource });
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
KEY_CLOSE: function() {
|
||
|
|
if (this.sounds['CLOSE'] && this.sounds['CLOSE'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'CLOSE' });
|
||
|
|
}
|
||
|
|
|
||
|
|
this.POST(`https://menuv/close`, { uuid: this.uuid, r: this.resource });
|
||
|
|
this.CLOSE_MENU({ uuid: this.uuid });
|
||
|
|
},
|
||
|
|
KEY_CLOSE_ALL: function() {
|
||
|
|
if (this.sounds['CLOSE'] && this.sounds['CLOSE'].type == 'native') {
|
||
|
|
this.POST(`https://menuv/sound`, { key: 'CLOSE' });
|
||
|
|
}
|
||
|
|
|
||
|
|
this.POST(`https://menuv/close_all`, { r: this.resource });
|
||
|
|
this.RESET_MENU();
|
||
|
|
},
|
||
|
|
POST: function(url: string, data: object|[]) {
|
||
|
|
var request = new XMLHttpRequest();
|
||
|
|
|
||
|
|
request.open('POST', url, true);
|
||
|
|
request.open('POST', url, true);
|
||
|
|
request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||
|
|
request.send(JSON.stringify(data));
|
||
|
|
},
|
||
|
|
NEXT_INDEX: function(idx: number) {
|
||
|
|
if (idx == null || typeof idx == "undefined") { idx = this.index; }
|
||
|
|
|
||
|
|
let index = 0;
|
||
|
|
let newIndex = -2;
|
||
|
|
|
||
|
|
if (this.items.length <= 0) { return -1; }
|
||
|
|
|
||
|
|
while (newIndex < -1) {
|
||
|
|
if ((idx + 1 + index) < this.items.length) {
|
||
|
|
if (!this.items[(idx + 1 + index)].disabled) {
|
||
|
|
newIndex = (idx + 1 + index);
|
||
|
|
} else {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
} else if (index >= this.items.length) {
|
||
|
|
return -1;
|
||
|
|
} else {
|
||
|
|
const addIndex = (idx + 1 + index) - this.items.length;
|
||
|
|
|
||
|
|
if (addIndex < this.items.length) {
|
||
|
|
if (!this.items[addIndex].disabled) {
|
||
|
|
newIndex = addIndex;
|
||
|
|
} else {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (newIndex < 0) { return -1; }
|
||
|
|
|
||
|
|
return newIndex;
|
||
|
|
},
|
||
|
|
PREV_INDEX: function(idx: number) {
|
||
|
|
if (idx == null || typeof idx == "undefined") { idx = this.index; }
|
||
|
|
|
||
|
|
let index = 0;
|
||
|
|
let newIndex = -2;
|
||
|
|
|
||
|
|
if (this.items.length <= 0) { return -1; }
|
||
|
|
|
||
|
|
while (newIndex < -1) {
|
||
|
|
if ((idx - 1 - index) >= 0) {
|
||
|
|
if (!this.items[(idx - 1 - index)].disabled) {
|
||
|
|
newIndex = (idx - 1 - index);
|
||
|
|
} else {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
} else if (index >= this.items.length) {
|
||
|
|
return -1;
|
||
|
|
} else {
|
||
|
|
const addIndex = (idx - 1 - index) + this.items.length;
|
||
|
|
|
||
|
|
if (addIndex < this.items.length && addIndex >= 0) {
|
||
|
|
if (!this.items[addIndex].disabled) {
|
||
|
|
newIndex = addIndex;
|
||
|
|
} else {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (newIndex < 0) { return -1; }
|
||
|
|
|
||
|
|
return newIndex;
|
||
|
|
},
|
||
|
|
NL2BR: function(text: string, replaceMode: boolean, isXhtml: boolean) {
|
||
|
|
var breakTag = (isXhtml) ? '<br />' : '<br>';
|
||
|
|
var replaceStr = (replaceMode) ? '$1'+ breakTag : '$1'+ breakTag +'$2';
|
||
|
|
|
||
|
|
return (text + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, replaceStr);
|
||
|
|
},
|
||
|
|
FORMAT_TEXT: function(text: string) {
|
||
|
|
text = this.ENSURE(text, '');
|
||
|
|
|
||
|
|
text = text.replace(/\^0/g, '<span style="color: black !important;">');
|
||
|
|
text = text.replace(/\^1/g, '<span style="color: red !important;">');
|
||
|
|
text = text.replace(/\^2/g, '<span style="color: green !important;">');
|
||
|
|
text = text.replace(/\^3/g, '<span style="color: yellow !important;">');
|
||
|
|
text = text.replace(/\^4/g, '<span style="color: blue !important;">');
|
||
|
|
text = text.replace(/\^5/g, '<span style="color: cyan !important;">');
|
||
|
|
text = text.replace(/\^6/g, '<span style="color: purple !important;">');
|
||
|
|
text = text.replace(/\^7/g, '<span style="color: white !important;">');
|
||
|
|
text = text.replace(/\^8/g, '<span style="color: darkred !important;">');
|
||
|
|
text = text.replace(/\^9/g, '<span style="color: gray !important;">');
|
||
|
|
text = text.replace(/~r~/g, '<span style="color: red !important;">');
|
||
|
|
text = text.replace(/~g~/g, '<span style="color: green !important;">');
|
||
|
|
text = text.replace(/~b~/g, '<span style="color: blue !important;">');
|
||
|
|
text = text.replace(/~y~/g, '<span style="color: yellow !important;">');
|
||
|
|
text = text.replace(/~p~/g, '<span style="color: purple !important;">');
|
||
|
|
text = text.replace(/~c~/g, '<span style="color: gray !important;">');
|
||
|
|
text = text.replace(/~m~/g, '<span style="color: darkgray !important;">');
|
||
|
|
text = text.replace(/~u~/g, '<span style="color: black !important;">');
|
||
|
|
text = text.replace(/~o~/g, '<span style="color: orange !important;">');
|
||
|
|
text = text.replace(/~n~/g, '<br />');
|
||
|
|
text = text.replace(/~s~/g, '<span style="color: white !important;">');
|
||
|
|
text = text.replace(/~h~/g, '<strong>');
|
||
|
|
|
||
|
|
const d = new DOMParser();
|
||
|
|
const domObj = d.parseFromString(text || "", "text/html");
|
||
|
|
|
||
|
|
return domObj.body.innerHTML;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|