forked from cswendrowski/FoundryVTT-Custom-CSS
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathccss-editor.js
More file actions
176 lines (155 loc) · 5.98 KB
/
ccss-editor.js
File metadata and controls
176 lines (155 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import { Settings } from './settings.js';
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
// const { HTMLCodeMirrorElement } = foundry.applications.elements;
/**
* A form for inputting Custom CSS settings.
*
* @export
* @class CcssEditor
* @extends {HandlebarsApplicationMixin(ApplicationV2)}
*/
export class CcssEditor extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
id: "ccss-settings-form",
classes: ["sheet", "ccss-editor"],
tag: "form",
position: {
width: 500,
height: 500
},
window: {
resizable: true,
title: "CCSS.settings.settingsMenu.title",
contentClasses: ["standard-form", "ccss-stylesheet-container"]
},
form: {
handler: CcssEditor.ccssFormHandler,
submitOnChange: false,
closeOnSubmit: false
}
}
static PARTS = {
stylesheet: {
template: "modules/custom-css/templates/settings.hbs",
},
footer: {
template: "templates/generic/form-footer.hbs",
}
}
_configureRenderOptions(options) {
super._configureRenderOptions(options);
options.parts = [];
options.parts.push("stylesheet");
options.parts.push("footer");
}
/**
* Track dirty state for the form.
*/
_dirty = false;
/**
* Process form submission for the sheet
* @this {CcssEditor} The handler is called with the application as its bound scope
* @param {SubmitEvent} event The originating form submission event
* @param {HTMLFormElement} form The form element that was submitted
* @param {FormDataExtended} formData Processed data for the submitted form
* @returns {Promise<void>}
*/
static async ccssFormHandler(event, form, formData) {
// Update settings with form data
await Settings.updateStylesheets(formData.object.worldStylesheet, formData.object.userStylesheet);
this._dirty = false; // Reset dirty state after submission
if (event.submitter.name == "ccss-save") {
// If the Save button was clicked, close the form
await this.close();
}
}
/**
* Construct an object of data to be passed to this froms HTML template.
*
* @param {string} partId - The part being rendered
* @param {ApplicationRenderContext} context - The shared context provided by _prepareContext
* @returns {Promise<ApplicationRenderContext>} Context data for the form part
* @protected
*/
async _preparePartContext(partId, context) {
context.partId = `${this.id}-${partId}`;
context.isGM = game.user.isGM;
context.worldStylesheet = Settings.getStylesheet("world");
context.userStylesheet = Settings.getStylesheet("user");
context.buttons = [
{ type: "submit", icon: "fas fa-check", label: "CCSS.settings.apply", name: "ccss-apply" },
{ type: "submit", icon: "fas fa-save", label: "CCSS.settings.save", name: "ccss-save" }
];
return context;
}
/**
* Handles editor resizing.
*
* @param {element} element - The drag handle element.
* @param {string} direction - The direction of the drag handle.
* @memberof CcssEditor
*/
dragElement(element, direction) {
var md;
const first = document.getElementById("ccss-world-stylesheet");
const second = document.getElementById("ccss-user-stylesheet");
const splitter = document.getElementById("ccss-super-container");
element.onmousedown = onMouseDown;
function onMouseDown(e) {
md = {
e,
offsetLeft: element.offsetLeft,
offsetTop: element.offsetTop,
offsetBottom: element.offsetBottom,
firstWidth: first.offsetWidth,
secondWidth: second.offsetWidth,
firstHeight: first.offsetHeight,
secondHeight: (splitter.offsetHeight - first.offsetHeight)
};
document.onmousemove = onMouseMove;
document.onmouseup = () => {
document.onmousemove = document.onmouseup = null;
}
}
function onMouseMove(e) {
var delta = {
x: e.clientX - md.e.x,
y: e.clientY - md.e.y
};
if (direction === "H") {
delta.x = Math.min(Math.max(delta.x, -md.firstWidth),
md.secondWidth);
element.style.left = md.offsetLeft + delta.x + "px";
first.style.width = (md.firstWidth + delta.x) + "px";
second.style.width = (md.secondWidth - delta.x) + "px";
}
if (direction === "V") {
delta.y = Math.min(Math.max(delta.y, -md.firstHeight), md.secondHeight);
element.style.top = md.offsetTop + delta.y + "px";
first.style.height = (md.firstHeight + delta.y) + "px";
second.style.height = (md.secondHeight - delta.y) + "px";
}
}
}
/**
* Set dynamic window height after rendering using the ApplicationV2 lifecycle hook.
* @param {object} context - The rendering context.
* @param {object} options - Render options.
*/
_onRender(context, options) {
this.setPosition({
height: game.user.isGM ? 900 : 500
});
if (game.user.isGM) {
this.dragElement(document.getElementById("ccss-separator"), "V");
}
// Track dirty state on input/change
const form = this.element;
if (form) {
form.addEventListener('input', () => { this._dirty = true; });
form.addEventListener('change', () => { this._dirty = true; });
}
}
}
// const app = new CcssEditor();
// app.render(true);