PageSourceSearch

https://wdn-cdn.unl.edu/wdn/templates_6.1/js/components/component.image-cropper.js?v=6.1.6

js unl.edu collected 2026-09-24 06:52:12 UTC 27,333 bytes, 496 lines download raw bytes

1var __defProp = Object.defineProperty;
2var __name = (target, value) => __defProp(target, "name", { value, configurable: !0 });
3import { u as uuidv4 } from "../chunks/chunk.dcf-utility.js?v=6.1.6";
4import { D as DCFCollapsibleFieldsets, U as UNLCollapsibleFieldset } from "../chunks/chunk.unl-collapsible-fieldset.js?v=6.1.6";
5class DCFImageCropper {
6  static {
7    __name(this, "DCFImageCropper");
8  }
9  uuid = uuidv4();
10  cropperElement = null;
11  cropperCanvas = null;
12  cropperCanvasContext = null;
13  imageSource = null;
14  imageToBeCropped = null;
15  statusElement = null;
16  guideFieldsetElement = null;
17  gridGuidesCheckbox = null;
18  gridGuides = !1;
19  centerGuidesCheckbox = null;
20  centerGuides = !1;
21  cropperScaleRange = null;
22  croppedX = -1;
23  croppedY = -1;
24  croppedScale = 100;
25  minCroppedScale = 25;
26  cropperMaxWidth = -1;
27  croppedRatio = 1;
28  canvasSize = 300;
29  croppedImageOutputWidth = 1e3;
30  imagePreviews = [];
31  mouseState = {
32    down: !1,
33    moved: !1,
34    downX: -1,
35    croppedX: -1,
36    downY: -1,
37    croppedY: -1
38  };
39  constructor(imageCropper, options = {}) {
40    if (this.cropperElement = imageCropper, (this.cropperElement.getAttribute("id") === "" || this.cropperElement.getAttribute("id") === null) && this.cropperElement.setAttribute("id", this.uuid.concat("-image-cropper-container")), this.imageSource = document.getElementById(this.cropperElement.dataset.imageCropperInput), this.imageSource === null)
41      throw new Error("Missing image cropper file input");
42    switch (this.canvasSize = parseInt(this.cropperElement.dataset.maxCanvasWidth, 10), (this.canvasSize <= 20 || isNaN(this.canvasSize)) && (this.canvasSize = 300), this.croppedImageOutputWidth = parseInt(this.cropperElement.dataset.croppedImageOutputWidth, 10), (this.croppedImageOutputWidth <= 20 || isNaN(this.croppedImageOutputWidth)) && (this.croppedImageOutputWidth = 1e3), this.cropperElement.dataset.ratio) {
43      case "1x1":
44        this.croppedRatio = 1;
45        break;
46      case "16x9":
47        this.croppedRatio = 16 / 9;
48        break;
49      case "9x16":
50        this.croppedRatio = 9 / 16;
51        break;
52      case "3x4":
53        this.croppedRatio = 3 / 4;
54        break;
55      case "4x3":
56        this.croppedRatio = 4 / 3;
57        break;
58      default:
59        this.croppedRatio = 1;
60    }
61    this.#setInnerHTMLCropper(), this.statusElement = document.getElementById(this.uuid.concat("-image-cropper-status")), this.imagePreviews = document.querySelectorAll(`.dcf-image-cropper-preview[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`), this.#setInnerHTMLPreviews(), this.cropperCanvas = document.getElementById(this.uuid.concat("-image-cropper-canvas")), this.cropperCanvasContext = this.cropperCanvas.getContext("2d"), this.cropperScaleRange = document.getElementById(this.uuid.concat("-image-cropper-scale")), this.guideFieldsetElement = document.getElementById(this.uuid.concat("-image-cropper-guides")), this.#setUpEventListeners(), options.collapsibleFieldset === void 0 ? new DCFCollapsibleFieldsets(this.guideFieldsetElement, options) : new options.collapsibleFieldset(this.guideFieldsetElement, options), this.#changeState(), this.cropperElement.classList.add("dcf-image-cropper-initialized"), this.cropperElement.removeAttribute("hidden"), this.imagePreviews.forEach((previewElement) => {
62      previewElement.removeAttribute("hidden");
63    }), this.cropperElement.dispatchEvent(new CustomEvent(DCFImageCropper.events("imageCropperReady"), {
64      detail: {
65        classInstance: this
66      }
67    }));
68  }
69  // The names of the events to be used easily
70  static events(name) {
71    const events = {
72      imageCropperReady: "imageCropperReady"
73    };
74    return Object.freeze(events), name in events ? events[name] : void 0;
75  }
76  /**
77   * Sets the inner HTML to the cropped element
78   * @returns { Void }
79   */
80  #setInnerHTMLCropper() {
81    this.cropperElement.innerHTML = `
82<div class="dcf-image-cropper-no-image">
83    <p>No image selected</p>
84</div>
85<section
86    class="dcf-image-cropper-yes-image dcf-d-none"
87    aria-labelledby="${this.uuid.concat("-image-cropper-title")}"
88>
89    <p id="${this.uuid.concat("-image-cropper-title")}" class="dcf-sr-only">Image Cropper Tool</p>
90    <div class="dcf-d-flex dcf-flex-row-rev dcf-flex-wrap dcf-jc-center dcf-ai-center dcf-gap-3 dcf-mb-3">
91        <div class="dcf-d-flex dcf-flex-col dcf-jc-center dcf-ai-center dcf-mb-3">
92            <p>Preview</p>
93            <div
94                class="dcf-image-cropper-preview"
95                data-image-cropper-input="${this.cropperElement.dataset.imageCropperIn
95put}"
96                data-max-canvas-width="${this.canvasSize / 3}"
97                hidden
98            ></div>
99        </div>
100        <canvas
101            id="${this.uuid.concat("-image-cropper-canvas")}"
102            class="dcf-b-grey dcf-b-2 dcf-b-solid"
103            height="225"
104            width="300"
105            tabindex="0"
106            aria-label="Image Crop Area Display"
107            role="img"
108            aria-describedby="${this.uuid.concat("-image-cropper-instructions")}"
109        ></canvas>
110    </div>
111    <div id="${this.uuid.concat("-image-cropper-status")}" role="status" aria-live="polite" class="dcf-sr-only"></div>
112
113    <div class="dcf-input-group dcf-col-gap-vw dcf-mb-3">
114        <label for="${this.uuid.concat("-image-cropper-scale")}">Selection size: </label>
115        <input
116            id="${this.uuid.concat("-image-cropper-scale")}"
117            type="range" min="${this.minCroppedScale}"
118            max="100"
119            value="100"
120            aria-controls="${this.uuid.concat("-image-cropper-canvas")}">
121    </div>
122
123    <fieldset class="dcf-collapsible-fieldset" data-start-expanded="false" id="${this.uuid.concat("-image-cropper-guides")}">
124        <legend>Guides</legend>
125        <div class="dcf-d-flex dcf-flex-row dcf-gap-3">
126            <div class="dcf-input-checkbox">
127                <input
128                    id="${this.uuid.concat("-image-cropper-grid-guides")}"
129                    type="checkbox"
130                    aria-controls="${this.uuid.concat("-image-cropper-canvas")}"
131                >
132                <label for="${this.uuid.concat("-image-cropper-grid-guides")}">Grid guides </label>
133            </div>
134            <div class="dcf-input-checkbox">
135                <input
136                    id="${this.uuid.concat("-image-cropper-center-guides")}"
137                    type="checkbox"
138                    aria-controls="${this.uuid.concat("-image-cropper-canvas")}"
139                >
140                <label for="${this.uuid.concat("-image-cropper-center-guides")}">Center guides </label>
141            </div>
142        </div>
143    </fieldset>
144
145    <p id="${this.uuid.concat("-image-cropper-instructions")}" class="dcf-txt-sm dcf-mt-3">
146        To select a portion of your image, click and drag the cropped area to position
147        it, or use the arrow keys for precise adjustments. Modify the size of the cropped area
148        using the slider or fine-tune with the plus and minus buttons for a personalized fit.
149        Toggle on the guides to help align your cropped area perfectly.
150    </p>
151</section>`;
152  }
153  /**
154   * Sets the inner HTML for all the preview elements
155   * @returns { Void }
156   */
157  #setInnerHTMLPreviews() {
158    this.imagePreviews.forEach((previewElement, index) => {
159      previewElement.innerHTML = `
160<div class="dcf-image-cropper-yes-image dcf-d-none">
161    <canvas
162        id="${this.uuid.concat(`-image-cropper-preview-canvas-${index}`)}"
163        class="dcf-b-grey dcf-b-2 dcf-b-solid"
164        height="225"
165        width="300"
166        aria-label="Cropped Image Preview"
167        role="img"></canvas>
168</div>
169`;
170    });
171  }
172  /**
173   * Sets up event listeners for the various interactive elements
174   * @returns { Void }
175   */
176  #setUpEventListeners() {
177    this.imageSource.addEventListener("change", this.#changeState.bind(this)), this.cropperScaleRange.addEventListener("input", () => {
178      this.updateScale();
179    }), this.guideFieldsetElement.addEventListener("collapsibleFieldsetReady", () => {
180      this.gridGuidesCheckbox = document.getElementById(this.uuid.concat("-image-cropper-grid-guides")), this.gridGuidesCheckbox.addEventListener("change", () => {
181        this.gridGuides = this.gridGuidesCheckbox.checked, this.#draw();
182      }), this.centerGuidesCheckbox = document.getElementById(this.uuid.concat("-image-cropper-center-guides")), this.centerGuidesCheckbox.addEventListener("change", () => {
183        this.centerGuides = this.centerGuidesCheckbox.checked, this.#draw();
184      });
185    }), this.cropperCanvas.addEventListener("mousedown", (event) => {
186      event.preventDefault(), this.mouseState.down = !0, this.mouseState.moved = !1, this.mouseState.downX = event.clientX, this.mouseState.croppedX = this.croppedX, this.mouseState.downY = event.clientY, this.mouseState.croppedY = this.croppedY;
187    }), this.cropperCanvas.addEventListener("mousemove", (event) => {
188      if (!this.mouseState.down)
189        return;
190      event.preventDefault(), this.mouseState.moved = !0;
191      const deltaX = event.clientX - this.mouseState.downX, deltaY = event.clientY - this.mouseState.downY;
192      this.croppedX = this.mouseState.croppedX + deltaX, this.croppedY = this.mouseState.croppedY + deltaY, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs(), this.mouseState.downX = event.clientX, this.mouseState.croppedX = this.croppedX, this.mouseState.downY = event.clientY, this.mouseState.croppedY = this.croppedY;
193    }), this.cropperCanvas.addEventListener("mouseup", (event) => {
194      if (this.mouseState.down) {
195        if (event.preventDefault(), !this.mouseState.moved) {
196          const boundingRect = this.cropperCanvas.getBoundingClientRect();
197          this.croppedX = this.mouseState.downX - boundingRect.x, this.croppedY = this.mouseState.downY - boundingRect.y, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
198        }
199        this.mouseState.down = !1, this.mouseState.moved = !1, this.mouseState.downX = -1, this.mouseState.croppedX = -1, this.mouseState.downY = -1, this.mouseState.croppedY = -1;
200      }
201    }), this.cropperCanvas.addEventListener("mouseleave", () => {
202      this.mouseState.down && (this.mouseState.down = !1, this.mouseState.moved = !1, this.mouseState.downX = -1, this.mouseState.croppedX = -1, this.mouseState.downY = -1, this.mouseState.croppedY = -1);
203    }), this.cropperElement.addEventListener("keydown", (event) => {
204      switch (event.key) {
205        case "ArrowRight":
206          this.moveRight(), event.preventDefault();
207          break;
208        case "ArrowLeft":
209          this.moveLeft(), event.preventDefault();
210          break;
211        case "ArrowDown":
212          this.moveDown(), event.preventDefault();
213          break;
214        case "ArrowUp":
215          this.moveUp(), event.preventDefault();
216          break;
217        case "+":
218        case "=":
219          this.grow(), event.preventDefault();
220          break;
221        case "-":
222        case "_":
223          this.shrink(), event.preventDefault();
224          break;
225      }
226    });
227  }
228  /**
229   * When the image source changes this will update the component's state
230   * @returns { Void }
231   */
232  async #changeState() {
233    if (this.imageSource.value === "") {
234      this.cropperElement.querySelector(".dcf-image-cropper-yes-image").classList.add("dcf-d-none"), this.cropperElement.querySelector(".dcf-image-cropper-no-image").classList.remove("dcf-d-none"), this.imagePreviews.forEach((previewElement) => {
235        previewElement.querySelector(".dcf-image-cropper-yes-image").classList.add("dcf-d-none");
236      }), this.#clearInputs();
237      return;
238    }
239    this.imageToBeCropped = await this.#getSrcImage(), this.#setUpCanvas(), this.croppedX = 0, this.croppedY = 0, this.croppedScale = 100, this.#draw(), this.cropperElement.querySelector(".dcf-image-cropper-yes-image").classList.remove("dcf-d-none"), this.cropperElement.querySelector(".dcf-image-cropper-no-image").classList.add("dcf-d-none"), this.imagePreviews.forEach((previewElement) => {
240      previewElement.querySelector(".dcf-image-cropper-yes-image").classList.remove("dcf-d-none");
241    }), this.#syncInputs();
242  }
243  /**
244   * Update the scale value based on the input range
245   * - This also re-draws canvases and syncs inputs
246   * @returns { Void }
247   */
248  updateScale() {
249    this.croppedScale = parseInt(this.cropperScaleRange.value, 10), this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
250  }
251  /**
252   * Move the selected area up by inputted amount
253   * - This also re-draws canvases and syncs inputs
254   * @returns { Void }
255   */
256  moveUp(delta = 5) {
257    this.croppedY -= delta, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
258  }
259  /**
260   * Move the selected area down by inputted amount
261   * - This also re-draws canvases and syncs inputs
262   * @returns { Void }
263   */
264  moveDown(delta = 5) {
265    this.croppedY += delta, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
266  }
267  /**
268   * Move the selected area left by inputted amount
269   * - This also re-draws canvases and syncs inputs
270   * @returns { Void }
271   */
272  moveLeft(delta = 5) {
273    this.croppedX -= delta, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
274  }
275  /**
276   * Move the selected area right by inputted amount
277   * - This also re-draws canvases and syncs inputs
278   * @returns { Void }
279   */
280  moveRight(delta = 5) {
281    this.croppedX += delta, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
282  }
283  /**
284   * Grows the selected area by inputted amount
285   * - This also re-draws canvases and syncs inputs
286   * @returns { Void }
287   */
288  grow(delta = 5) {
289    this.croppedScale += delta, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
290  }
291  /**
292   * Shrinks the selected area by inputted amount
293   * - This also re-draws canvases and syncs inputs
294   * @returns { Void }
295   */
296  shrink(delta = 5) {
297    this.croppedScale -= delta, this.#checkIfBoxIsInBounds(), this.#draw(), this.#syncInputs();
298  }
299  /**
300   * Checks and fixes position of the selected area to avoid it going outside the image
301   * @returns { Void }
302   */
303  #checkIfBoxIsInBounds() {
304    this.croppedScale < this.minCroppedScale && (this.croppedScale = this.minCroppedScale), this.croppedScale > 100 && (this.croppedScale = 100);
305    const croppedWidth = this.cropperMaxWidth * (this.croppedScale / 100), croppedHeight = this.cropperMaxWidth * (this.croppedScale / 100) / this.croppedRatio;
306    this.croppedX > this.cropperCanvas.width - croppedWidth && (this.croppedX = this.cropperCanvas.width - croppedWidth), this.croppedY > this.cropperCanvas.height - croppedHeight && (this.croppedY = this.cropperCanvas.height - croppedHeight), this.croppedY < 0 && (this.croppedY = 0), this.croppedX < 0 && (this.croppedX = 0);
307  }
308  /**
309   * Draw the image, selected area, and preview images on their canvases
310   * @returns { Void }
311   */
312  #draw() {
313    this.cropperCanvasContext.drawImage(
314      this.imageToBeCropped,
315      0,
316      0,
317      this.cropperCanvas.width,
318      this.cropperCanvas.height
319    ), this.cropperCanvasContext.strokeStyle = "black", this.cropperCanvasContext.lineWidth = 4, this.#drawLines(), this.cropperCanvasContext.strokeStyle = "white", this.cropperCanvasContext.lineWidth = 2, this.#drawLines();
320    const croppedWidth = this.cropperMaxWidth * (this.croppedScale / 100), croppedHeight = this.cropperMaxWidth * (this.croppedScale / 100) / this.croppedRatio;
321    this.imagePreviews.forEach((previewElement) => {
322      const previewCanvas = previewElement.querySelector("canvas"), previewContext = previewCanvas.getContext("2d");
323      let previewSize = parseInt(previewElement.dataset.maxCanvasWidth, 10);
324      previewSize <= 20 && (previewSize = this.canvasSize), this.croppedRatio > 1 ? (previewCanvas.width = previewSize, previewCanvas.height = previewSize / this.croppedRatio) : (previewCanvas.width = previewSize / (1 / this.croppedRatio), previewCanvas.height = previewSize);
325      const scaleX = this.imageToBeCropped.width / this.cropperCanvas.width, scaleY = this.imageToBeCropped.height / this.cropperCanvas.height, scaledX = this.croppedX * scaleX, scaledY = this.croppedY * scaleY, scaledWidth = croppedWidth * scaleX, scaledHeight = croppedHeight * scaleY;
326      previewContext.drawImage(
327        this.imageToBeCropped,
328        scaledX,
329        scaledY,
330        scaledWidth,
331        scaledHeight,
332        // source rect (in original image)
333        0,
334        0,
335        previewCanvas.width,
336        previewCanvas.height
337        // destination rect (fit to preview canvas)
338      );
339    });
340  }
341  /**
342   * Inner function for #draw which only will draw the lines
343   * This logic is used multiple times for the black and white lines
344   */
345  #drawLines() {
346    const croppedWidth = this.cropperMaxWidth * (this.croppedScale / 100), croppedHeight = this.cropperMaxWidth * (this.croppedScale / 100) / this.croppedRatio;
347    this.centerGuides && (this.cropperCanvasContext.beginPath(), this.cropperCanvasContext.moveTo(this.croppedX, this.croppedY), this.cropperCanvasContext.lineTo(this.croppedX + croppedWidth, this.croppedY + croppedHeight), this.cropperCanvasContext.moveTo(this.croppedX, this.croppedY + croppedHeight), this.cropperCanvasContext.lineTo(this.croppedX + croppedWidth, this.croppedY), this.cropperCanvasContext.stroke()), this.gridGuides && (this.cropperCanvasContext.beginPath(), this.cropperCanvasContext.moveTo(this.croppedX + croppedWidth / 3, this.croppedY), this.cropperCanvasContext.lineTo(this.croppedX + croppedWidth / 3, this.croppedY + croppedHeight), this.cropperCanvasContext.moveTo(this.croppedX + 2 * croppedWidth / 3, this.croppedY), this.cropperCanvasContext.lineTo(this.croppedX + 2 * croppedWidth / 3, this.croppedY + croppedHeight), this.cropperCanvasContext.moveTo(this.croppedX, this.croppedY + croppedHeight / 3), this.cropperCanvasContext.lineTo(this.croppedX + croppedWidth, this.croppedY + croppedHeight / 3), this.cropperCanvasContext.moveTo(this.croppedX, this.croppedY + 2 * croppedHeight / 3), this.cropperCanvasContext.lineTo(this.croppedX + croppedWidth, this.croppedY + 2 * croppedHeight / 3), this.cropperCanvasContext.stroke()), this.cropperCanvasContext.strokeRect(this.croppedX, this.croppedY, croppedWidth, croppedHeight);
348  }
349  /**
350   * Resets all inputs and status to default state where there is no image
351   * @returns { Void }
352   */
353  #clearInputs() {
354    this.cropperScaleRange.value = "100", this.statusElement.innerText = "", document.querySelectorAll(`.dcf-image-cropper-x[data-image-cropper-input="${this.cropperElement.dataset.imageCropperIn
354put}"]`).forEach((inputElement) => {
355      inputElement.value = "-1";
356    }), document.querySelectorAll(`.dcf-image-cropper-x2[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
357      inputElement.value = "-1";
358    }), document.querySelectorAll(`.dcf-image-cropper-y[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
359      inputElement.value = "-1";
360    }), document.querySelectorAll(`.dcf-image-cropper-y2[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
361      inputElement.value = "-1";
362    }), document.querySelectorAll(`.dcf-image-cropper-width[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
363      inputElement.value = "-1";
364    }), document.querySelectorAll(`.dcf-image-cropper-height[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
365      inputElement.value = "-1";
366    }), document.querySelectorAll(`.dcf-image-cropper-ratio[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
367      inputElement.value = this.croppedRatio.toFixed(2);
368    }), document.querySelectorAll(`.dcf-image-cropper-ratio-text[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
369      switch (this.croppedRatio.toFixed(2)) {
370        case (3 / 4).toFixed(2):
371          inputElement.value = "3x4";
372          break;
373        case (4 / 3).toFixed(2):
374          inputElement.value = "4x3";
375          break;
376        case (9 / 16).toFixed(2):
377          inputElement.value = "9x16";
378          break;
379        case (16 / 9).toFixed(2):
380          inputElement.value = "16x9";
381          break;
382        default:
383          inputElement.value = "1x1";
384      }
385    }), document.querySelectorAll(`.dcf-image-cropper-cropped-image[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
386      inputElement.value = "";
387    });
388  }
389  /**
390   * Updates all inputs and status to match the current state of the cropped area
391   * @returns { Void }
392   */
393  #syncInputs() {
394    this.cropperScaleRange.value = this.croppedScale;
395    const scaleX = this.imageToBeCropped.width / this.cropperCanvas.width, scaleY = this.imageToBeCropped.height / this.cropperCanvas.height, croppedWidth = this.cropperMaxWidth * (this.croppedScale / 100), croppedHeight = this.cropperMaxWidth * (this.croppedScale / 100) / this.croppedRatio, xPos = (scaleX * this.croppedX).toFixed(2), yPos = (scaleY * this.croppedY).toFixed(2), width = (scaleX * croppedWidth).toFixed(2);
396    let aspectRatio = "1x1";
397    switch (this.croppedRatio.toFixed(2)) {
398      case (3 / 4).toFixed(2):
399        aspectRatio = "3x4";
400        break;
401      case (4 / 3).toFixed(2):
402        aspectRatio = "4x3";
403        break;
404      case (9 / 16).toFixed(2):
405        aspectRatio = "9x16";
406        break;
407      case (16 / 9).toFixed(2):
408        aspectRatio = "16x9";
409        break;
410      default:
411        aspectRatio = "1x1";
412    }
413    this.statusElement.innerText = `Cropped area moved to ${xPos}, ${yPos} with a width of ${width} in an aspect ratio of ${aspectRatio}.`, document.querySelectorAll(`.dcf-image-cropper-x[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
414      inputElement.value = xPos;
415    }), document.querySelectorAll(`.dcf-image-cropper-x2[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
416      inputElement.value = (scaleX * (this.croppedX + croppedWidth)).toFixed(2);
417    }), document.querySelectorAll(`.dcf-image-cropper-y[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
418      inputElement.value = yPos;
419    }), document.querySelectorAll(`.dcf-image-cropper-y2[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
420      inputElement.value = (scaleY * (this.croppedY + croppedHeight)).toFixed(2);
421    }), document.querySelectorAll(`.dcf-image-cropper-width[data-image-cropper-input="${this.cropperElement.dataset.imageCropperIn
421put}"]`).forEach((inputElement) => {
422      inputElement.value = width;
423    }), document.querySelectorAll(`.dcf-image-cropper-height[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
424      inputElement.value = (scaleY * croppedHeight).toFixed(2);
425    }), document.querySelectorAll(`.dcf-image-cropper-ratio[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
426      inputElement.value = this.croppedRatio.toFixed(2);
427    }), document.querySelectorAll(`.dcf-image-cropper-ratio-text[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`).forEach((inputElement) => {
428      inputElement.value = aspectRatio;
429    });
430    const croppedImageInputs = document.querySelectorAll(`.dcf-image-cropper-cropped-image[data-image-cropper-input="${this.cropperElement.dataset.imageCropperInput}"]`);
431    croppedImageInputs.length > 0 && this.#getCroppedImageSrc().then((croppedImageFile) => {
432      croppedImageInputs.forEach((inputElement) => {
433        const dataTransferObj = new DataTransfer();
434        dataTransferObj.items.add(croppedImageFile), inputElement.files = dataTransferObj.files;
435      });
436    });
437  }
438  /**
439   * Sets up the cropper canvas to match the aspect ratio of the of the image to be cropped
440   * @returns { Void }
441   */
442  #setUpCanvas() {
443    const aspectRatio = this.imageToBeCropped.width / this.imageToBeCropped.height;
444    this.imageToBeCropped.width > this.imageToBeCropped.height ? (this.cropperCanvas.width = this.canvasSize, this.cropperCanvas.height = this.canvasSize / aspectRatio) : (this.cropperCanvas.width = this.canvasSize / (1 / aspectRatio), this.cropperCanvas.height = this.canvasSize), this.cropperCanvas.width / this.croppedRatio > this.cropperCanvas.height ? this.cropperMaxWidth = this.cropperCanvas.height / (1 / this.croppedRatio) : this.cropperMaxWidth = this.cropperCanvas.width;
445  }
446  /**
447   * Gets the image file for the inputted image
448   * @returns { Promise<HTMLImageElement> }
449   */
450  #getSrcImage() {
451    return new Promise((resolve, reject) => {
452      this.imageSource.files[0] === void 0 && reject();
453      const imageFile = this.imageSource.files[0], imageFileURL = URL.createObjectURL(imageFile), imageObj = new Image();
454      imageObj.onload = () => {
455        URL.revokeObjectURL(imageFileURL), resolve(imageObj);
456      }, imageObj.src = imageFileURL;
457    });
458  }
459  /**
460   * Gets the cropped image file based on the inputted image and the selected area
461   * @async
462   * @returns { Promise<File> }
463   */
464  async #getCroppedImageSrc() {
465    const hiddenCanvas = document.createElement("canvas"), hiddenCanvasContext = hiddenCanvas.getContext("2d");
466    hiddenCanvas.width = this.croppedImageOutputWidth, hiddenCanvas.height = this.croppedImageOutputWidth / this.croppedRatio;
467    const croppedWidth = this.cropperMaxWidth * (this.croppedScale / 100), croppedHeight = this.cropperMaxWidth * (this.croppedScale / 100) / this.croppedRatio, scaleX = this.imageToBeCropped.width / this.cropperCanvas.width, scaleY = this.imageToBeCropped.height / this.cropperCanvas.height, scaledX = this.croppedX * scaleX, scaledY = this.croppedY * scaleY, scaledWidth = croppedWidth * scaleX, scaledHeight = croppedHeight * scaleY;
468    hiddenCanvasContext.drawImage(
469      this.imageToBeCropped,
470      scaledX,
471      scaledY,
472      scaledWidth,
473      scaledHeight,
474      // source rect (in original image)
475      0,
476      0,
477      hiddenCanvas.width,
478      hiddenCanvas.height
479      // destination rect (fit to preview canvas)
480    );
481    const blob = await new Promise((resolve) => hiddenCanvas.toBlob(resolve, this.imageToBeCropped.type));
482    return new File([blob], "cropped_image", { type: this.imageToBeCropped.type });
483  }
484}
485class UNLImageCropper extends DCFImageCropper {
486  static {
487    __name(this, "UNLImageCropper");
488  }
489  constructor(imageCropper, options = {}) {
490    "collapsibleFieldset" in options || (options.collapsibleFieldset = UNLCollapsibleFieldset), super(imageCropper, options), window.UNL = window.UNL || {}, window.UNL.classes = window.UNL.classes || {}, window.UNL.classes[this.cropperElement.getAttribute("id")] = this, this.cropperElement.dispatchEvent(new Event("UNLClassReady"));
491  }
492}
493export {
494  UNLImageCropper as default
495};
496//# sourceMappingURL=component.image-cropper.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.