imageviewer.js 8.7 KB
Newer Older
A
AUTOMATIC 已提交
1
// A full size 'lightbox' preview modal shown when left clicking on gallery previews
D
DepFA 已提交
2
function closeModal() {
3
    gradioApp().getElementById("lightboxModal").style.display = "none";
D
DepFA 已提交
4 5
}

6
function showModal(event) {
7
    const source = event.target || event.srcElement;
8 9 10
    const modalImage = gradioApp().getElementById("modalImage");
    const lb = gradioApp().getElementById("lightboxModal");
    modalImage.src = source.src;
11 12 13
    if (modalImage.style.display === 'none') {
        lb.style.setProperty('background-image', 'url(' + source.src + ')');
    }
14
    lb.style.display = "flex";
15
    lb.focus();
16

17 18
    const tabTxt2Img = gradioApp().getElementById("tab_txt2img");
    const tabImg2Img = gradioApp().getElementById("tab_img2img");
19 20
    // show the save button in modal only on txt2img or img2img tabs
    if (tabTxt2Img.style.display != "none" || tabImg2Img.style.display != "none") {
21
        gradioApp().getElementById("modal_save").style.display = "inline";
22
    } else {
23
        gradioApp().getElementById("modal_save").style.display = "none";
24
    }
25
    event.stopPropagation();
D
DepFA 已提交
26 27
}

28
function negmod(n, m) {
29
    return ((n % m) + m) % m;
30 31
}

32
function updateOnBackgroundChange() {
33
    const modalImage = gradioApp().getElementById("modalImage");
34
    if (modalImage && modalImage.offsetParent) {
S
space-nuko 已提交
35
        let currentButton = selected_gallery_button();
36
        let preview = gradioApp().querySelectorAll('.livePreview > img');
37
        if (opts.js_live_preview_in_modal_lightbox && preview.length > 0) {
38 39 40
            // show preview image if available
            modalImage.src = preview[preview.length - 1].src;
        } else if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
41 42
            modalImage.src = currentButton.children[0].src;
            if (modalImage.style.display === 'none') {
A
AUTOMATIC 已提交
43
                const modal = gradioApp().getElementById("lightboxModal");
44
                modal.style.setProperty('background-image', `url(${modalImage.src})`);
45 46
            }
        }
47
    }
48 49 50
}

function modalImageSwitch(offset) {
S
space-nuko 已提交
51
    var galleryButtons = all_gallery_buttons();
52 53

    if (galleryButtons.length > 1) {
S
space-nuko 已提交
54
        var currentButton = selected_gallery_button();
55

56
        var result = -1;
57 58
        galleryButtons.forEach(function(v, i) {
            if (v == currentButton) {
59
                result = i;
60
            }
61
        });
62 63

        if (result != -1) {
64 65
            var nextButton = galleryButtons[negmod((result + offset), galleryButtons.length)];
            nextButton.click();
66 67 68 69
            const modalImage = gradioApp().getElementById("modalImage");
            const modal = gradioApp().getElementById("lightboxModal");
            modalImage.src = nextButton.children[0].src;
            if (modalImage.style.display === 'none') {
70
                modal.style.setProperty('background-image', `url(${modalImage.src})`);
71 72
            }
            setTimeout(function() {
73 74
                modal.focus();
            }, 10);
75
        }
76
    }
77
}
D
DepFA 已提交
78

79 80 81 82 83
function saveImage() {
    const tabTxt2Img = gradioApp().getElementById("tab_txt2img");
    const tabImg2Img = gradioApp().getElementById("tab_img2img");
    const saveTxt2Img = "save_txt2img";
    const saveImg2Img = "save_img2img";
84
    if (tabTxt2Img.style.display != "none") {
85
        gradioApp().getElementById(saveTxt2Img).click();
86
    } else if (tabImg2Img.style.display != "none") {
87
        gradioApp().getElementById(saveImg2Img).click();
88
    } else {
89
        console.error("missing implementation for saving modal of this type");
90 91 92 93
    }
}

function modalSaveImage(event) {
94 95
    saveImage();
    event.stopPropagation();
96 97
}

98
function modalNextImage(event) {
99 100
    modalImageSwitch(1);
    event.stopPropagation();
D
DepFA 已提交
101 102
}

103
function modalPrevImage(event) {
104 105
    modalImageSwitch(-1);
    event.stopPropagation();
106 107
}

108
function modalKeyHandler(event) {
109
    switch (event.key) {
110 111 112 113 114 115 116 117 118 119 120 121
    case "s":
        saveImage();
        break;
    case "ArrowLeft":
        modalPrevImage(event);
        break;
    case "ArrowRight":
        modalNextImage(event);
        break;
    case "Escape":
        closeModal();
        break;
122 123 124
    }
}

A
AUTOMATIC 已提交
125
function setupImageForLightbox(e) {
126 127 128
    if (e.dataset.modded) {
        return;
    }
A
AUTOMATIC 已提交
129

130 131 132
    e.dataset.modded = true;
    e.style.cursor = 'pointer';
    e.style.userSelect = 'none';
A
AUTOMATIC 已提交
133

134
    var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
A
AUTOMATIC 已提交
135

136 137 138 139
    // For Firefox, listening on click first switched to next image then shows the lightbox.
    // If you know how to fix this without switching to mousedown event, please.
    // For other browsers the event is click to make it possiblr to drag picture.
    var event = isFirefox ? 'mousedown' : 'click';
A
AUTOMATIC 已提交
140

141
    e.addEventListener(event, function(evt) {
142 143 144 145 146
        if (evt.button == 1) {
            open(evt.target.src);
            evt.preventDefault();
            return;
        }
147
        if (!opts.js_modal_lightbox || evt.button != 0) return;
A
AUTOMATIC 已提交
148

149 150 151 152
        modalZoomSet(gradioApp().getElementById('modalImage'), opts.js_modal_lightbox_initially_zoomed);
        evt.preventDefault();
        showModal(evt);
    }, true);
D
typo  
DepFA 已提交
153 154 155

}

156
function modalZoomSet(modalImage, enable) {
157
    if (modalImage) modalImage.classList.toggle('modalImageFullscreen', !!enable);
158 159
}

160
function modalZoomToggle(event) {
161
    var modalImage = gradioApp().getElementById("modalImage");
162 163
    modalZoomSet(modalImage, !modalImage.classList.contains('modalImageFullscreen'));
    event.stopPropagation();
D
DepFA 已提交
164 165
}

166
function modalTileImageToggle(event) {
167 168 169 170 171
    const modalImage = gradioApp().getElementById("modalImage");
    const modal = gradioApp().getElementById("lightboxModal");
    const isTiling = modalImage.style.display === 'none';
    if (isTiling) {
        modalImage.style.display = 'block';
172
        modal.style.setProperty('background-image', 'none');
173 174
    } else {
        modalImage.style.display = 'none';
175
        modal.style.setProperty('background-image', `url(${modalImage.src})`);
176 177
    }

178
    event.stopPropagation();
179 180
}

181
onAfterUiUpdate(function() {
182
    var fullImg_preview = gradioApp().querySelectorAll('.gradio-gallery > div > img');
183
    if (fullImg_preview != null) {
A
AUTOMATIC 已提交
184
        fullImg_preview.forEach(setupImageForLightbox);
D
DepFA 已提交
185
    }
186
    updateOnBackgroundChange();
187
});
188 189

document.addEventListener("DOMContentLoaded", function() {
A
AUTOMATIC 已提交
190
    //const modalFragment = document.createDocumentFragment();
191
    const modal = document.createElement('div');
D
DepFA 已提交
192
    modal.onclick = closeModal;
D
DepFA 已提交
193
    modal.id = "lightboxModal";
194 195
    modal.tabIndex = 0;
    modal.addEventListener('keydown', modalKeyHandler, true);
D
DepFA 已提交
196

197
    const modalControls = document.createElement('div');
198 199
    modalControls.className = 'modalControls gradio-container';
    modal.append(modalControls);
200

201
    const modalZoom = document.createElement('span');
D
DepFA 已提交
202
    modalZoom.className = 'modalZoom cursor';
203 204
    modalZoom.innerHTML = '⤡';
    modalZoom.addEventListener('click', modalZoomToggle, true);
205
    modalZoom.title = "Toggle zoomed view";
206
    modalControls.appendChild(modalZoom);
207

208
    const modalTileImage = document.createElement('span');
209
    modalTileImage.className = 'modalTileImage cursor';
210 211
    modalTileImage.innerHTML = '⊞';
    modalTileImage.addEventListener('click', modalTileImageToggle, true);
212
    modalTileImage.title = "Preview tiling";
213
    modalControls.appendChild(modalTileImage);
214

215 216 217 218 219 220 221
    const modalSave = document.createElement("span");
    modalSave.className = "modalSave cursor";
    modalSave.id = "modal_save";
    modalSave.innerHTML = "🖫";
    modalSave.addEventListener("click", modalSaveImage, true);
    modalSave.title = "Save Image(s)";
    modalControls.appendChild(modalSave);
222

223
    const modalClose = document.createElement('span');
224
    modalClose.className = 'modalClose cursor';
225
    modalClose.innerHTML = '×';
226
    modalClose.onclick = closeModal;
227
    modalClose.title = "Close image viewer";
228
    modalControls.appendChild(modalClose);
D
DepFA 已提交
229

230
    const modalImage = document.createElement('img');
D
DepFA 已提交
231 232
    modalImage.id = 'modalImage';
    modalImage.onclick = closeModal;
233 234 235
    modalImage.tabIndex = 0;
    modalImage.addEventListener('keydown', modalKeyHandler, true);
    modal.appendChild(modalImage);
D
DepFA 已提交
236

237
    const modalPrev = document.createElement('a');
238
    modalPrev.className = 'modalPrev';
239 240
    modalPrev.innerHTML = '❮';
    modalPrev.tabIndex = 0;
241
    modalPrev.addEventListener('click', modalPrevImage, true);
242 243
    modalPrev.addEventListener('keydown', modalKeyHandler, true);
    modal.appendChild(modalPrev);
244

245
    const modalNext = document.createElement('a');
246
    modalNext.className = 'modalNext';
247 248
    modalNext.innerHTML = '❯';
    modalNext.tabIndex = 0;
249
    modalNext.addEventListener('click', modalNextImage, true);
250
    modalNext.addEventListener('keydown', modalKeyHandler, true);
251

252
    modal.appendChild(modalNext);
253

A
AlUlkesh 已提交
254
    try {
255 256 257 258
        gradioApp().appendChild(modal);
    } catch (e) {
        gradioApp().body.appendChild(modal);
    }
259

A
AUTOMATIC 已提交
260
    document.body.appendChild(modal);
261

262
});