This commit is contained in:
2026-07-07 21:08:52 +02:00
commit 4c20cfc716
2613 changed files with 318021 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
#controls {
font-family: "Poppins", sans-serif;
font-size: 2.77vh;
color: #fff;
position: absolute;
bottom: 3.7vh;
right: 3.7vh;
}
.controls {
display: none;
}
.dialog {
font-family: "Poppins", sans-serif;
background: #212121;
color: #fff;
position: absolute;
border-radius: 0.46vh;
overflow: hidden;
top: 50%;
left: 50%;
width: 55.6vh;
height: 14.1vh;
padding-bottom: 1vh;
transform: translate(-50%, -50%);
}
.head {
display: flex;
flex-basis: 100%;
align-items: center;
justify-content: center;
color: #fff;
font-size: 1.6vh;
font-weight: 500;
text-transform: uppercase;
}
.dialog.big {
height: 18.5vh;
}
.dialog .head {
background: #161616;
text-align: center;
height: 3.7vh;
}
.dialog .head span::before {
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.dialog input[type="text"] {
width: 60%;
height: 2.96vh;
outline: 0;
background: none;
text-align: center;
margin-top: 2.4vh;
margin-left: 11.6vh;
font-size: 1.48vh;
transition: all 0.2s ease-in-out;
color: white;
border: 0.05vh solid #ffffff3b;
border-radius: 0.3vh;
}
.dialog input[type="text"]:active,
.dialog input[type="text"]:hover {
color: white;
}
.dialog textarea {
width: 100%;
height: 11.85vh;
}
.dialog button[name="submit"] {
width: 17.6%;
height: 2.96vh;
margin-left: 14.8vh;
font-weight: 500;
color: #fb9b04;
border-radius: 0.5vh;
font-size: 1.2vh;
background: #fb9c0433;
outline: 0;
border: none;
transition: all 0.2s ease-in-out;
}
.dialog button {
z-index: 9999;
transform: translate(-0%, 50%);
}
.dialog button[name="cancel"] {
width: 17.6%;
height: 2.96vh;
margin-left: 5.6vh;
font-weight: 500;
color: #fefefe;
border-radius: 0.5vh;
font-size: 1.2vh;
background: #94949433;
outline: 0;
border: none;
transition: all 0.2s ease-in-out;
}
.dialog button[name="cancel"]:hover {
letter-spacing: 0.09vh;
transform: scale(1.05) translate(-0%, 50%);
}
.dialog button[name="submit"]:hover {
letter-spacing: 0.09vh;
transform: scale(1.05) translate(-0%, 50%);
}
* {
font-family: Poppins !important;
}

Binary file not shown.

View File

@@ -0,0 +1,181 @@
(function () {
let MenuTpl =
'<div id="menu_{{_namespace}}_{{_name}}" class="dialog {{#isBig}}big{{/isBig}}">' +
'<div class="head"><span>{{title}}</span></div>' +
'{{#isDefault}}<input type="text" name="value" id="inputText"/>{{/isDefault}}' +
'{{#isBig}}<textarea name="value"/>{{/isBig}}' +
'<button type="button" name="submit">Submit</button>' +
'<button type="button" name="cancel">Cancel</button>' +
"</div>" +
"</div>";
window.ESX_MENU = {};
ESX_MENU.ResourceName = "esx_menu_dialog";
ESX_MENU.opened = {};
ESX_MENU.focus = [];
ESX_MENU.pos = {};
ESX_MENU.open = function (namespace, name, data) {
if (typeof ESX_MENU.opened[namespace] === "undefined") {
ESX_MENU.opened[namespace] = {};
}
if (typeof ESX_MENU.opened[namespace][name] != "undefined") {
ESX_MENU.close(namespace, name);
}
if (typeof ESX_MENU.pos[namespace] === "undefined") {
ESX_MENU.pos[namespace] = {};
}
if (typeof data.type === "undefined") {
data.type = "default";
}
if (typeof data.align === "undefined") {
data.align = "top-left";
}
data._index = ESX_MENU.focus.length;
data._namespace = namespace;
data._name = name;
ESX_MENU.opened[namespace][name] = data;
ESX_MENU.pos[namespace][name] = 0;
ESX_MENU.focus.push({
namespace: namespace,
name: name,
});
document.onkeyup = function (key) {
if (key.which === 27) {
// Escape key
SendMessage(ESX_MENU.ResourceName, "menu_cancel", data);
} else if (key.which === 13) {
// Enter key
SendMessage(ESX_MENU.ResourceName, "menu_submit", data);
}
};
ESX_MENU.render();
};
ESX_MENU.close = function (namespace, name) {
delete ESX_MENU.opened[namespace][name];
for (let i = 0; i < ESX_MENU.focus.length; i++) {
if (ESX_MENU.focus[i].namespace === namespace && ESX_MENU.focus[i].name === name) {
ESX_MENU.focus.splice(i, 1);
break;
}
}
ESX_MENU.render();
};
ESX_MENU.render = function () {
let menuContainer = $("#menus")[0];
$(menuContainer).find('button[name="submit"]').unbind("click");
$(menuContainer).find('button[name="cancel"]').unbind("click");
$(menuContainer).find('[name="value"]').unbind("input propertychange");
menuContainer.innerHTML = "";
$(menuContainer).hide();
for (let namespace in ESX_MENU.opened) {
for (let name in ESX_MENU.opened[namespace]) {
let menuData = ESX_MENU.opened[namespace][name];
let view = JSON.parse(JSON.stringify(menuData));
switch (menuData.type) {
case "default": {
view.isDefault = true;
break;
}
case "big": {
view.isBig = true;
break;
}
default:
break;
}
let menu = $(Mustache.render(MenuTpl, view))[0];
$(menu).css("z-index", 1000 + view._index);
$(menu)
.find('button[name="submit"]')
.click(
function () {
ESX_MENU.submit(this.namespace, this.name, this.data);
}.bind({ namespace: namespace, name: name, data: menuData })
);
$(menu)
.find('button[name="cancel"]')
.click(
function () {
ESX_MENU.cancel(this.namespace, this.name, this.data);
}.bind({ namespace: namespace, name: name, data: menuData })
);
$(menu)
.find('[name="value"]')
.bind(
"input propertychange",
function () {
this.data.value = $(menu).find('[name="value"]').val();
ESX_MENU.change(this.namespace, this.name, this.data);
}.bind({ namespace: namespace, name: name, data: menuData })
);
if (typeof menuData.value != "undefined") {
$(menu).find('[name="value"]').val(menuData.value);
}
menuContainer.appendChild(menu);
}
}
$(menuContainer).show();
$("#inputText").focus();
};
ESX_MENU.submit = function (namespace, name, data) {
SendMessage(ESX_MENU.ResourceName, "menu_submit", data);
};
ESX_MENU.cancel = function (namespace, name, data) {
SendMessage(ESX_MENU.ResourceName, "menu_cancel", data);
};
ESX_MENU.change = function (namespace, name, data) {
SendMessage(ESX_MENU.ResourceName, "menu_change", data);
};
ESX_MENU.getFocused = function () {
return ESX_MENU.focus[ESX_MENU.focus.length - 1];
};
window.onData = (data) => {
switch (data.action) {
case "openMenu": {
ESX_MENU.open(data.namespace, data.name, data.data);
break;
}
case "closeMenu": {
ESX_MENU.close(data.namespace, data.name);
break;
}
}
};
window.onload = function (e) {
window.addEventListener("message", (event) => {
onData(event.data);
});
};
})();

View File

@@ -0,0 +1,347 @@
(function defineMustache(global, factory) {
if (typeof exports === "object" && exports && typeof exports.nodeName !== "string") {
factory(exports);
} else if (typeof define === "function" && define.amd) {
define(["exports"], factory);
} else {
global.Mustache = {};
factory(global.Mustache);
}
})(this, function mustacheFactory(mustache) {
var objectToString = Object.prototype.toString;
var isArray =
Array.isArray ||
function isArrayPolyfill(object) {
return objectToString.call(object) === "[object Array]";
};
function isFunction(object) {
return typeof object === "function";
}
function typeStr(obj) {
return isArray(obj) ? "array" : typeof obj;
}
function escapeRegExp(string) {
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
function hasProperty(obj, propName) {
return obj != null && typeof obj === "object" && propName in obj;
}
var regExpTest = RegExp.prototype.test;
function testRegExp(re, string) {
return regExpTest.call(re, string);
}
var nonSpaceRe = /\S/;
function isWhitespace(string) {
return !testRegExp(nonSpaceRe, string);
}
var entityMap = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;", "/": "&#x2F;", "`": "&#x60;", "=": "&#x3D;" };
function escapeHtml(string) {
return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap(s) {
return entityMap[s];
});
}
var whiteRe = /\s*/;
var spaceRe = /\s+/;
var equalsRe = /\s*=/;
var curlyRe = /\s*\}/;
var tagRe = /#|\^|\/|>|\{|&|=|!/;
function parseTemplate(template, tags) {
if (!template) return [];
var sections = [];
var tokens = [];
var spaces = [];
var hasTag = false;
var nonSpace = false;
function stripSpace() {
if (hasTag && !nonSpace) {
while (spaces.length) delete tokens[spaces.pop()];
} else {
spaces = [];
}
hasTag = false;
nonSpace = false;
}
var openingTagRe, closingTagRe, closingCurlyRe;
function compileTags(tagsToCompile) {
if (typeof tagsToCompile === "string") tagsToCompile = tagsToCompile.split(spaceRe, 2);
if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) throw new Error("Invalid tags: " + tagsToCompile);
openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + "\\s*");
closingTagRe = new RegExp("\\s*" + escapeRegExp(tagsToCompile[1]));
closingCurlyRe = new RegExp("\\s*" + escapeRegExp("}" + tagsToCompile[1]));
}
compileTags(tags || mustache.tags);
var scanner = new Scanner(template);
var start, type, value, chr, token, openSection;
while (!scanner.eos()) {
start = scanner.pos;
value = scanner.scanUntil(openingTagRe);
if (value) {
for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
chr = value.charAt(i);
if (isWhitespace(chr)) {
spaces.push(tokens.length);
} else {
nonSpace = true;
}
tokens.push(["text", chr, start, start + 1]);
start += 1;
if (chr === "\n") stripSpace();
}
}
if (!scanner.scan(openingTagRe)) break;
hasTag = true;
type = scanner.scan(tagRe) || "name";
scanner.scan(whiteRe);
if (type === "=") {
value = scanner.scanUntil(equalsRe);
scanner.scan(equalsRe);
scanner.scanUntil(closingTagRe);
} else if (type === "{") {
value = scanner.scanUntil(closingCurlyRe);
scanner.scan(curlyRe);
scanner.scanUntil(closingTagRe);
type = "&";
} else {
value = scanner.scanUntil(closingTagRe);
}
if (!scanner.scan(closingTagRe)) throw new Error("Unclosed tag at " + scanner.pos);
token = [type, value, start, scanner.pos];
tokens.push(token);
if (type === "#" || type === "^") {
sections.push(token);
} else if (type === "/") {
openSection = sections.pop();
if (!openSection) throw new Error('Unopened section "' + value + '" at ' + start);
if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
} else if (type === "name" || type === "{" || type === "&") {
nonSpace = true;
} else if (type === "=") {
compileTags(value);
}
}
openSection = sections.pop();
if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
return nestTokens(squashTokens(tokens));
}
function squashTokens(tokens) {
var squashedTokens = [];
var token, lastToken;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
token = tokens[i];
if (token) {
if (token[0] === "text" && lastToken && lastToken[0] === "text") {
lastToken[1] += token[1];
lastToken[3] = token[3];
} else {
squashedTokens.push(token);
lastToken = token;
}
}
}
return squashedTokens;
}
function nestTokens(tokens) {
var nestedTokens = [];
var collector = nestedTokens;
var sections = [];
var token, section;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
token = tokens[i];
switch (token[0]) {
case "#":
case "^":
collector.push(token);
sections.push(token);
collector = token[4] = [];
break;
case "/":
section = sections.pop();
section[5] = token[2];
collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
break;
default:
collector.push(token);
}
}
return nestedTokens;
}
function Scanner(string) {
this.string = string;
this.tail = string;
this.pos = 0;
}
Scanner.prototype.eos = function eos() {
return this.tail === "";
};
Scanner.prototype.scan = function scan(re) {
var match = this.tail.match(re);
if (!match || match.index !== 0) return "";
var string = match[0];
this.tail = this.tail.substring(string.length);
this.pos += string.length;
return string;
};
Scanner.prototype.scanUntil = function scanUntil(re) {
var index = this.tail.search(re),
match;
switch (index) {
case -1:
match = this.tail;
this.tail = "";
break;
case 0:
match = "";
break;
default:
match = this.tail.substring(0, index);
this.tail = this.tail.substring(index);
}
this.pos += match.length;
return match;
};
function Context(view, parentContext) {
this.view = view;
this.cache = { ".": this.view };
this.parent = parentContext;
}
Context.prototype.push = function push(view) {
return new Context(view, this);
};
Context.prototype.lookup = function lookup(name) {
var cache = this.cache;
var value;
if (cache.hasOwnProperty(name)) {
value = cache[name];
} else {
var context = this,
names,
index,
lookupHit = false;
while (context) {
if (name.indexOf(".") > 0) {
value = context.view;
names = name.split(".");
index = 0;
while (value != null && index < names.length) {
if (index === names.length - 1) lookupHit = hasProperty(value, names[index]);
value = value[names[index++]];
}
} else {
value = context.view[name];
lookupHit = hasProperty(context.view, name);
}
if (lookupHit) break;
context = context.parent;
}
cache[name] = value;
}
if (isFunction(value)) value = value.call(this.view);
return value;
};
function Writer() {
this.cache = {};
}
Writer.prototype.clearCache = function clearCache() {
this.cache = {};
};
Writer.prototype.parse = function parse(template, tags) {
var cache = this.cache;
var tokens = cache[template];
if (tokens == null) tokens = cache[template] = parseTemplate(template, tags);
return tokens;
};
Writer.prototype.render = function render(template, view, partials) {
var tokens = this.parse(template);
var context = view instanceof Context ? view : new Context(view);
return this.renderTokens(tokens, context, partials, template);
};
Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) {
var buffer = "";
var token, symbol, value;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
value = undefined;
token = tokens[i];
symbol = token[0];
if (symbol === "#") value = this.renderSection(token, context, partials, originalTemplate);
else if (symbol === "^") value = this.renderInverted(token, context, partials, originalTemplate);
else if (symbol === ">") value = this.renderPartial(token, context, partials, originalTemplate);
else if (symbol === "&") value = this.unescapedValue(token, context);
else if (symbol === "name") value = this.escapedValue(token, context);
else if (symbol === "text") value = this.rawValue(token);
if (value !== undefined) buffer += value;
}
return buffer;
};
Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) {
var self = this;
var buffer = "";
var value = context.lookup(token[1]);
function subRender(template) {
return self.render(template, context, partials);
}
if (!value) return;
if (isArray(value)) {
for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
}
} else if (typeof value === "object" || typeof value === "string" || typeof value === "number") {
buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
} else if (isFunction(value)) {
if (typeof originalTemplate !== "string") throw new Error("Cannot use higher-order sections without the original template");
value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
if (value != null) buffer += value;
} else {
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
}
return buffer;
};
Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) {
var value = context.lookup(token[1]);
if (!value || (isArray(value) && value.length === 0)) return this.renderTokens(token[4], context, partials, originalTemplate);
};
Writer.prototype.renderPartial = function renderPartial(token, context, partials) {
if (!partials) return;
var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
if (value != null) return this.renderTokens(this.parse(value), context, partials, value);
};
Writer.prototype.unescapedValue = function unescapedValue(token, context) {
var value = context.lookup(token[1]);
if (value != null) return value;
};
Writer.prototype.escapedValue = function escapedValue(token, context) {
var value = context.lookup(token[1]);
if (value != null) return mustache.escape(value);
};
Writer.prototype.rawValue = function rawValue(token) {
return token[1];
};
mustache.name = "mustache.js";
mustache.version = "2.3.0";
mustache.tags = ["{{", "}}"];
var defaultWriter = new Writer();
mustache.clearCache = function clearCache() {
return defaultWriter.clearCache();
};
mustache.parse = function parse(template, tags) {
return defaultWriter.parse(template, tags);
};
mustache.render = function render(template, view, partials) {
if (typeof template !== "string") {
throw new TypeError('Invalid template! Template should be a "string" ' + 'but "' + typeStr(template) + '" was given as the first ' + "argument for mustache#render(template, view, partials)");
}
return defaultWriter.render(template, view, partials);
};
mustache.to_html = function to_html(template, view, partials, send) {
var result = mustache.render(template, view, partials);
if (isFunction(send)) {
send(result);
} else {
return result;
}
};
mustache.escape = escapeHtml;
mustache.Scanner = Scanner;
mustache.Context = Context;
mustache.Writer = Writer;
return mustache;
});

View File

@@ -0,0 +1,16 @@
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="nui://esx_menu_dialog/html/css/app.css" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
</head>
<body>
<div id="menus"></div>
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
<script src="nui://es_extended/html/js/wrapper.js"></script>
<script src="nui://esx_menu_dialog/html/js/mustache.min.js" type="text/javascript"></script>
<script src="nui://esx_menu_dialog/html/js/app.js" type="text/javascript"></script>
</body>
</html>