I want to make my photo captions editable and then save the changes in localstorage. It works for the first photo but when I want to edit another, changes are saved to this first photo and not the one I edited. Here's part of my code where I display photos with captions:
<div class="gallery">
<a href="<?=$path1; ?>">
<img src="<?= $path1; ?>">
</a>
<div id="contenteditable">
<p id="caption-photo" contenteditable> <?=pathinfo($path1, PATHINFO_FILENAME)?></p>
</div>
</div>
And it is my js code to save the changes:
const editables = document.querySelectorAll("[contenteditable]");
editables.forEach(el => {
el.addEventListener("blur", () => {
localStorage.setItem("dataStorage-" + el.id, el.innerHTML);
})
});
for (var key in localStorage) {
if (key.includes("dataStorage-")) {
const id = key.replace("dataStorage-","");
document.querySelector("#" + id).innerHTML = localStorage.getItem(key);
}
}
Okay lemme open your mind a bit ... also pardon me for the many answers, I just like comprehensive answers:
Create a new php
file with the name update_file.php
and put it within the same directory. Then put the php
code that handles the requests in this file.
Why is this important? Because we are depending on the responseText being received from the php file which will tell us whether the request was successful or not. And, when the php that handles the request is within the same file as the html
, the request will return a response containing the html
content of the page --- You can experiment this yourself and see that if you put the code below within the same file, the responseText
will be the whole code in the page, and that's not what we want, we want either 0 or 1 ... ok, enough said:
Put this in update_file.php
in the same directory as the current file:
<?php
if(isset($_GET["old_name"]) && isset($_GET["new_name"]) && isset($_GET["directory"]) && isset($_GET["extension"])){
$old_name = $_GET["old_name"];
$new_name = $_GET["new_name"];
// The new values from the GET request
$directory = $_GET["directory"];
$extension = $_GET["extension"];
// echo $directory;
// echo $extension;
// Concatenate the values with the directories
// 1 thing to note, if the image is in the current directory,
// the value you will receive for $directory will be "."
// So the method below ensures flexibility with different directories
$dot = ".";
// $dot is added before the extension
$slash = "/";
// $slash is added after the directory name
// if ".", it will be "./' -- for current directory
// if "some/directory" , it will be "some/directory/"
// Then add to the file name and the extension
$full_oldname = $directory . $slash . $old_name . $dot . $extension;
$full_newname = $directory . $slash . $new_name . $dot . $extension;
echo rename($full_oldname, $full_newname);
}
?>
Then this is your current file:
<?php
$some_records = ["record1.jpeg", "uploads/record2.jpeg", "images/subdirectory1/record3.jpeg", "images/record4.jpg", "images/subdirectory2/record5.jpg"];
// Assuming your directory has subdirectories
$counter = 1;
?>
<div class="gallery">
<?php foreach ($some_records as $path) {
echo '<a href="' . $path . '">
<img src="' . $path . '">
</a>
<div id="contenteditable">
<p id="caption-photo' . $counter . '" contenteditable>' . pathinfo($path, PATHINFO_FILENAME) . '</p>
<input type="hidden" name="directory-"' . $counter . '" value="' . pathinfo($path, PATHINFO_DIRNAME) . '" />
<input type="hidden" name="extension-"' . $counter . '" value="' . pathinfo($path, PATHINFO_EXTENSION) . '" />
</div>';
// Note the 2 hidden inputs above
$counter++;
}
?>
</div>
<script>
function update_file(old_name, new_name, directory, extension) {
// The function has been updated with the new parameters
var update = new XMLHttpRequest();
update.open("GET", "update_file.php?old_name=" + old_name + "&new_name=" + new_name + "&directory=" + directory + "&extension=" + extension, true);
// The XHR request has also been updated with the new values
update.onreadystatechange = function() {
if (this.readyState == this.DONE && this.status == 200) {
if (this.responseText != null) {
console.log(this.responseText);
// This will either be 0 or 1, if correct values have been passed to it
if(this.responseText == 1){
console.log("Renamed successfully!");
}
else {
console.log("Error renaming!");
}
}
else {
console.log("Not sent!!");
}
}
};
update.send();
}
document.addEventListener("DOMContentLoaded", function(){
const editables = document.querySelectorAll("[contenteditable]");
editables.forEach(el => {
var curr = el.innerHTML;
// The next element after "el" is the first hidden input with the directory
var dir = el.nextElementSibling.value;
// The next element after the above hidden input is the second hidden input with the extension
// Note the 2 ".nextElementSibling" accessors
var ext = el.nextElementSibling.nextElementSibling.value;
// To get the value of any input(that can lie within a form control) use "[element].value'
console.log(ext);
console.log(dir);
el.addEventListener("blur", () => {
localStorage.setItem("dataStorage-" + el.id, el.innerHTML);
console.log(el.innerHTML);
update_file(curr, el.innerHTML, dir, ext);
})
});
for(var i = 1; i < editables.length+1; i++){
console.log("dataStorage-caption-photo" + i + " => " + localStorage.getItem("dataStorage-caption-photo" + i));
}
});
</script>
Also read the comments, the main points here are:
Hope this helps
Here is some developer tools you can be using, I'm not sure which browser you are using but you might find such a similar thing, go to the console tab then click on settings and enable logging of XMLHttpRequests
You will be able to see the requests right after you remove focus on any contenteditable element and confirm whether they are being sent