Add media upload JS + CSS: image preview in composer, AJAX upload on submit, Twitter-style gallery grid, video embed styling
This commit is contained in:
+101
@@ -16,6 +16,7 @@
|
||||
var compose = feed.querySelector('[data-beep-compose]');
|
||||
if (compose) initCompose(compose, feed);
|
||||
initSortTabs(feed);
|
||||
initMedia(compose, feed);
|
||||
feed.addEventListener('click', onClick);
|
||||
feed.addEventListener('input', onInput);
|
||||
feed.addEventListener('keydown', onKeydown);
|
||||
@@ -63,6 +64,15 @@
|
||||
}
|
||||
input.value = '';
|
||||
refresh();
|
||||
|
||||
// Upload pending images to this new beep
|
||||
var pending = compose._beepPendingImages;
|
||||
if (pending && pending.length && data.id) {
|
||||
uploadPendingImages(data.id, pending, compose).then(function () {
|
||||
// Refresh the beep in the DOM to show uploaded images
|
||||
reloadFeed(feed, 'recent');
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
window.alert('Could not post. Please try again.');
|
||||
@@ -325,6 +335,97 @@
|
||||
return Array.from(s).length;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- Media upload (images) ---------- */
|
||||
function initMedia(compose, feed) {
|
||||
var input = compose.querySelector('[data-beep-media-input]');
|
||||
var preview = compose.querySelector('[data-beep-media-preview]');
|
||||
var counter = compose.querySelector('[data-beep-media-count]');
|
||||
if (!input) return;
|
||||
|
||||
var pendingImages = [];
|
||||
|
||||
input.addEventListener('change', function (e) {
|
||||
var files = Array.prototype.slice.call(e.target.files);
|
||||
if (!files.length) return;
|
||||
var room = 4 - pendingImages.length;
|
||||
if (room <= 0) { input.value = ''; return; }
|
||||
files = files.slice(0, room);
|
||||
files.forEach(function (file) {
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
window.alert('Image must be under 10 MB: ' + file.name);
|
||||
return;
|
||||
}
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (ev) {
|
||||
var url = ev.target.result;
|
||||
var id = 'pending-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);
|
||||
pendingImages.push({ file: file, previewUrl: url, id: id });
|
||||
renderPreviews();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
input.value = '';
|
||||
});
|
||||
|
||||
function renderPreviews() {
|
||||
if (!pendingImages.length) {
|
||||
preview.innerHTML = '';
|
||||
preview.hidden = true;
|
||||
if (counter) counter.hidden = true;
|
||||
return;
|
||||
}
|
||||
preview.hidden = false;
|
||||
if (counter) {
|
||||
counter.textContent = pendingImages.length + '/4';
|
||||
counter.hidden = false;
|
||||
}
|
||||
preview.innerHTML = pendingImages.map(function (img) {
|
||||
return '<div class="beep-media-preview-item" data-preview-id="' + img.id + '">' +
|
||||
'<img src="' + img.previewUrl + '">' +
|
||||
'<button class="beep-media-remove" type="button" title="Remove" data-remove="' + img.id + '">×</button>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
preview.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-remove]');
|
||||
if (!btn) return;
|
||||
var id = btn.dataset.remove;
|
||||
pendingImages = pendingImages.filter(function (img) { return img.id !== id; });
|
||||
renderPreviews();
|
||||
});
|
||||
|
||||
compose._beepPendingImages = pendingImages;
|
||||
}
|
||||
|
||||
function uploadPendingImages(postId, pendingImages, compose) {
|
||||
if (!pendingImages || !pendingImages.length) return Promise.resolve();
|
||||
var promises = pendingImages.map(function (img) {
|
||||
var formData = new FormData();
|
||||
formData.append('file', img.file);
|
||||
return fetch(config.restUrl + 'media/' + postId, {
|
||||
method: 'POST',
|
||||
headers: { 'X-WP-Nonce': config.nonce },
|
||||
credentials: 'same-origin',
|
||||
body: formData
|
||||
})
|
||||
.then(handleResponse)
|
||||
.catch(function (err) {
|
||||
console.warn('Image upload failed:', img.file.name, err);
|
||||
});
|
||||
});
|
||||
return Promise.all(promises).then(function () {
|
||||
pendingImages.length = 0;
|
||||
if (compose) {
|
||||
var preview = compose.querySelector('[data-beep-media-preview]');
|
||||
if (preview) { preview.innerHTML = ''; preview.hidden = true; }
|
||||
var counter = compose.querySelector('[data-beep-media-count]');
|
||||
if (counter) counter.hidden = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleResponse(res) {
|
||||
if (!res.ok) return res.json().then(function (j) { throw j; }, function () { throw res; });
|
||||
return res.json();
|
||||
|
||||
Reference in New Issue
Block a user