All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

192 lines
9.1 KiB

//injectConfig library by @theripper93
//License: MIT
//Documentation: https://github.com/theripper93/injectConfig
export var injectConfig = {
inject: function injectConfig(app,html,data,object){
this._generateTabStruct(app,html,data,object);
const tabSize = data.tab?.width ?? 100;
object = object || app.object;
const moduleId = data.moduleId;
let injectPoint
if(typeof data.inject === "string"){
injectPoint = html.find(data.inject).first().closest(".form-group");
}else{
injectPoint = data.inject;
}
injectPoint = injectPoint ? $(injectPoint) : (data.tab ? html.find("form > .tab").last() : html.find(".form-group").last());
let injectHtml = "";
for(const [k,v] of Object.entries(data)){
if(k === "moduleId" || k === "inject" || k === "tab") continue;
const elemData = data[k];
const flag = "flags." + moduleId + "." + (k || "");
const flagValue = object?.getFlag(moduleId, k) ?? elemData.default ?? getDefaultFlag(k);
const notes = v.notes ? `<p class="notes">${v.notes}</p>` : "";
v.label = v.units ? v.label+`<span class="units"> (${v.units})</span>` : v.label;
switch(elemData.type){
case "text":
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<input type="text" name="${flag}" ${elemData.dType ? `data-dtype="${elemData.dType}"` : ""} value="${flagValue}" placeholder="${v.placeholder || ""}">${notes}
</div>`;
break;
case "number":
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<input type="number" name="${flag}" min="${v.min}" max="${v.max}" step="${v.step ?? 1}" value="${flagValue}" placeholder="${v.placeholder || ""}">${notes}
</div>`;
break;
case "checkbox":
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<input type="checkbox" name="${flag}" ${flagValue ? "checked" : ""}>${notes}
</div>`;
break;
case "select":
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<select name="${flag}" ${elemData.dType ? `data-dtype="${elemData.dType}"` : ""}>`;
for(const [i,j] of Object.entries(v.options)){
injectHtml += `<option value="${i}" ${flagValue == i ? "selected" : ""}>${j}</option>`;
}
injectHtml += `</select>${notes}
</div>`;
break;
case "range":
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<div class="form-fields">
<input type="range" name="${flag}" value="${flagValue}" min="${v.min}" max="${v.max}" step="${v.step ?? 1}">
<span class="range-value">${flagValue}</span>${notes}
</div>
</div>`;
break;
case "color":
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<div class="form-fields">
<input class="color" type="text" name="${flag}" value="${flagValue}">
<input type="color" data-edit="${flag}" value="${flagValue}">
</div>
${notes}
</div>`;
break;
case "custom":
injectHtml += v.html;
break;
}
if(elemData.type?.includes("filepicker")){
const fpType = elemData.type.split(".")[1] || "imagevideo";
injectHtml += `<div class="form-group">
<label for="${k}">${v.label || ""}</label>
<div class="form-fields">
<button type="button" class="file-picker" data-extras="${elemData.fpTypes ? elemData.fpTypes.join(",") : ""}" data-type="${fpType}" data-target="${flag}" title="Browse Files" tabindex="-1">
<i class="fas fa-file-import fa-fw"></i>
</button>
<input class="image" type="text" name="${flag}" placeholder="${v.placeholder || ""}" value="${flagValue}">
</div>${notes}
</div>`;
}
}
injectHtml = $(injectHtml);
injectHtml.on("click", ".file-picker", this.fpTypes,_bindFilePicker);
injectHtml.on("change", `input[type="color"]`, _colorChange);
if(data.tab){
const injectTab = createTab(data.tab.name, data.tab.label, data.tab.icon).append(injectHtml);
injectPoint.after(injectTab);
app?.setPosition({"height" : "auto", "width" : data.tab ? app.options.width + tabSize : "auto"});
return injectHtml;
}
injectPoint.after(injectHtml);
if(app)app?.setPosition({"height" : "auto", "width" : data.tab ? app.options.width + tabSize : null});
return injectHtml;
function createTab(name,label,icon){
/*let tabs = html.find(".sheet-tabs").last();
if(!tabs.length) tabs = html.find(`nav[data-group="main"]`);*/
const tabs = html.find(".sheet-tabs").first().find(".item").last();
const tab = `<a class="item" data-tab="${name}"><i class="${icon}"></i> ${label}</a>`
tabs.after(tab);
const tabContainer = `<div class="tab" data-tab="${name}"></div>`
return $(tabContainer);
}
function getDefaultFlag(inputType){
switch(inputType){
case "number":
return 0;
case "checkbox":
return false;
}
return "";
}
function _colorChange(e){
const input = $(e.target);
const edit = input.data("edit");
const value = input.val();
injectHtml.find(`input[name="${edit}"]`).val(value);
}
function _bindFilePicker(event) {
event.preventDefault();
const button = event.currentTarget;
const input = $(button).closest(".form-fields").find("input") || null;
const extraExt = button.dataset.extras ? button.dataset.extras.split(",") : [];
const options = {
field: input[0],
type: button.dataset.type,
current: input.val() || null,
button: button,
}
const fp = new FilePicker(options);
fp.extensions ? fp.extensions.push(...extraExt) : fp.extensions = extraExt;
return fp.browse();
}
},
quickInject: function quickInject(injectData, data){
injectData = Array.isArray(injectData) ? injectData : [injectData];
for(const doc of injectData){
let newData = data
if(doc.inject){
newData = JSON.parse(JSON.stringify(data))
data.inject = doc.inject;
}
Hooks.on(`render${doc.documentName}Config`, (app,html)=>{ injectConfig.inject(app,html,newData) });
}
},
_generateTabStruct : function _generateTabStruct(app,html,data,object){
const isTabs = html.find(".sheet-tabs").length;
const useTabs = data.tab
if(isTabs || !useTabs) return;
const tabSize = data.tab?.width || 100;
const layer = app?.object?.layer?.options?.name
const icon = $(".main-controls").find(`li[data-canvas-layer="${layer}"]`).find("i").attr("class")
const $tabs = $(`<nav class="sheet-tabs tabs">
<a class="item active" data-tab="basic"><i class="${icon}"></i> ${game.i18n.localize("LIGHT.HeaderBasic")}</a>
</nav>
<div class="tab active" data-tab="basic"></div>`);
//move all content of form into tab
const form = html.find("form").first();
form.children().each((i,e)=>{
$($tabs[2]).append(e);
});
form.append($tabs);
const submitButton = html.find("button[type='submit']").first();
form.append(submitButton);
html.on("click", ".item", (e)=>{
html.find(".item").removeClass("active");
$(e.currentTarget).addClass("active");
html.find(".tab").removeClass("active");
html.find(`[data-tab="${e.currentTarget.dataset.tab}"]`).addClass("active");
app.setPosition({"height" : "auto", "width" : data.tab ? app.options.width + tabSize : "auto"});
});
}
}