Tinymce Image upload - save to database - javascript

I have configured my TinyMCE to use images_upload_url and images_upload_handler to post to a selected image to a server-side page which saves the image to a location on my server. In addition, this server-side page also saves the filename of the image as a record within a database.
I then have another server-side page which reads the database and constructs a JSON list of the images that have been uploaded. This JSON data is then pulled into my Tinymce instance using image_list, so that I can easily reuse previously uploaded images as opposed to having to reupload the same image more than once.
The specific lines of my tiny.init() are:
image_list: 'processes/image-list.php',
image_class_list: [
{title: 'None', value: ''},
{title: 'Full width image', value: 'img-responsive'}
],
images_upload_url: 'processes/upload-image.php',
images_upload_handler: function (blobInfo, success, failure) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', 'processes/upload-image-free.asp');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
},
image_dimensions: false,
All of this works as expected.
What I would like to do is also save a description of the image to the database so this can be outputted as the title within the JSON data of previously uploaded images.
As the upload feature only allows an image to be selected from a file system I cannot utilise the upload feature:
So I thought I could utilise the alternate description field of the image feature/modal but this would have to be done via a JavaScript triggered event that is triggered upon submitting the image feature/modal, that takes the content in the alternative description input field and POST this to a serverside page that can update the database.
Unless there is another way does anybody know how I can target the 'click' on the 'save' button within the image feature to extract the alternate description before the image feature/modal disappears and extract the input field content?
From there I should be able to work out how to get this to a server-side page to update the database.
Many thanks in advance

I have managed to resolve this so posting a solution to help others - though this is more than a hack.
Firstly on my form page after the tiny.init is loaded I am using the following:
document.addEventListener('keyup', logKey);
function logKey(e) {
labels = document.querySelectorAll(".tox-label");
for (i = 0; i < labels.length; ++i) {
if (labels[i].textContent == "Alternative description"){
imageDescription = document.getElementById(labels[i].htmlFor).value;
}
}
};
This loops through all the elements (labels in this case) which have a class of .toxlabel and if the textContent matches "Alternative description" then to capture the value in in a variable called 'imageDescription'.
Then within my tiny.init I have the following:
editor.on('ExecCommand', function(e) {
if (e.command == "mceUpdateImage"){
var http = new XMLHttpRequest();
var params = encodeURI('desc=' + imageDescription);
http.open('POST', 'processes/upload-image-description.asp', true);
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(params);
}
});
This code is actioned upon the mceUpdateImage modal closing, it takes the value stored within the imageDescription variable and posts it to a server-side page which updates the database.
I am sure there are cleaner ways but they would require more of a TinyMce understanding.

Related

How can I reassign XHR without reloading the page in JavaScript?

This is a PHP Bootstrap CODE I try to dynamically change bootstrap modal body content that can I can easily add or edit product category . Then I submit the entered or changed data to save into database by submitting the form through Ajax .
I use pure JavaScript Ajax request to done this job for me.
For the first time when I click into Create Product Category Everything work fine. But when the first time content add then I try to add anther product the second product will automatically add two times it will increase for the forth time and so on .
I know the problem . But I can't solve it.
how can I reassign or how can I Completely clean Ajax after the task done then after clicking to create new product category I will renew Ajax ?
this is my JavaScript Ajax code :
// get add category
document.getElementById('add_category').addEventListener('click', () => {
var xhr = new XMLHttpRequest();
xhr.open("GET", 'add.php', true);
console.log("add_category")
xhr.onload = function() {
if (this.status == 200) {
document.getElementById('exampleModalLabel').innerHTML = 'Create Product Category';
document.getElementById('modal-body').innerHTML = this.response;
// console.log(this.response)
dynamicChangePicture()
// on change category_name
onChangeCategoryName('category_name');
// add new Category
document.getElementById('save_btn').addEventListener('click', (e) => {
e.preventDefault();
console.log('save_btn')
var xhr = new XMLHttpRequest();
xhr.open('POST', `../includes/functions.php`, true)
xhr.onload = function() {
if (xhr.status == 200) {
console.log(xhr.response)
if (xhr.response == 'category name add successfully! ') {
document.getElementById('close_modal_btn').click();
showMessage(xhr.response, 'Add')
console.log(xhr.responseText)
// document.getElementById('logo_box').innerHTML = `<span class='text-success'>${xhr.response}</span>`;
} else {
showMessage(xhr.response, 'Remove')
document.getElementById('logo_box').innerHTML = `<span class='text-danger'>${xhr.response}</span>`;
}
setTimeout(() => {
document.getElementById('table-body').innerHTML = '';
defaultLoad();
console.log("data Loaded")
}, 5000)
}
}
const formData = new FormData(document.getElementById('add_category_form'))
xhr.send(formData);
})
}
}
xhr.send();
})
even I Change inside xhr variable with the a deferent one it will still have the same problem.

Why is my ajax request repeating same data from Laravel controller?

Goal: load more rows from the database to a view using an ajax request when a user clicks the "load more" button. I would like the data to load without a page reload.
Problem: The data being loaded via ajax keeps repeating the same rows on every request and doesn't paginate as per standard request.
Detail: I have a view that loads 4 rows from the database which I paginate using Laravel's built-in pagination. I've added an event listener on a "load more" button which successfully sends the request to the controller, which in turn successfully returns data. The controller returns a partial view of the data I want to display. However this data doesn't seem to increment properly and keeps repeating the records shown on each request. I am not sure what I am missing here, if the problem is in the controller or in the JS?
I am not very experienced with Laravel, PHP and JS since coming from more of a web designer and UI design background and would love to really understand what I am doing wrong here.
PLEASE NO JQUERY EXAMPLES.
Partial view:
#foreach ($products as $product)
<div style="background-color:pink; width: 200px;">
<p>{{ $product->title }}</p>
<img src="/images/product/{{ $product->img }}" alt="{{ $product->title }}" style="width: 50px;">
</div>
#endforeach
Javascript:
(I am updating the button href attribute so the request URL reflects the correct query)
const container = document.querySelector('#sandbox-container');
let button = document.getElementById('load-stuff');
let url = button.getAttribute('href'); // http://127.0.0.1:8000/sandbox?page=2
let pageNum = button.getAttribute('href').substr(35,1);
button.addEventListener('click', (event) => {
event.preventDefault();
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// if page loads successfully, replace the number at the end of the url with the incremented page number
pageNum++;
newUrl = url.replace(/page=([^d]*)/, `page=${pageNum}`);
button.setAttribute('href', newUrl);
xhr.onload = function() {
if (xhr.status === 200) {
container.insertAdjacentHTML('beforeend', xhr.responseText);
}
else {
console.log(`Request failed, this is the response: ${xhr.responseText}`);
}
};
xhr.send();
})
Controller:
public function sandbox(Request $request)
{
$products = Product::orderBy('title', 'asc')->paginate(4);
if($request->expectsJson()){
return view('sandbox-more', compact('products'));
} else {
return view('sandbox', compact('products'));
}
}
Consider this snippet for your javascript
const container = document.querySelector('#sandbox-container');
let button = document.getElementById('load-stuff');
button.addEventListener('click', (event) => {
event.preventDefault();
const xhr = new XMLHttpRequest();
let url = button.getAttribute('href');
let pageNum = button.getAttribute('data-page-number') || 0;
xhr.open('GET', url, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// if page loads successfully, replace the number at the end of the url with the incremented page number
pageNum++;
newUrl = url + '?page=' + pageNum;
xhr.onload = function() {
if (xhr.status === 200) {
container.insertAdjacentHTML('beforeend', xhr.responseText);
button.setAttribute('data-page-number', pageNum);
}
else {
console.log(`Request failed, this is the response: ${xhr.responseText}`);
}
};
xhr.send();
})
What I've done here is to have the page number saved to a dedicated custom attribute "data-page-number". Doing "button.getAttribute('href').substr(35,1)" is inefficient. And then check the page number and increment it on the button's click event. Also, only update the "data-page-number" attribute when the request has been successful. I hope this helps
You should regenerate the pagination every time you make a request to get the correct data. Here is a very good example on doing it via jQuery. Should just adjust it to your needs since you are using pure Javascript.

Load HTML Table from XMLHttpRequest response

I am loading my table on document.ready() from a json file as follows
document load....
$(document).ready(function () {
getSummaryData(function (data1) {
var dataarray=new Array();
dataarray.push(data1);
$('#summaryTable').DataTable({
data: dataarray,
"columns": [
---
---
and retrieving the data from a file as follows
function getSummaryData(cb_func1) {
$.ajax({
url: "data/summary.json",
success: cb_func1
});
console.log(cb_func1)
}
This was essentially loading dummy data so i could I could figure out how to load the table correctly etc. This works fine.
It does following
1. page loads
2. reads data from file
3. populates table
In reality, the data will not be loaded from file but will be returned from xhr response but I am unable to figure out
how to wire it all together. The use case is
POST a file via XMLHttpRequest
Get response
populate table (same data format as file)
I will post the file as follows...
<script>
var form = document.getElementById('form');
var fileSelect = document.getElementById('select');
var uploadButton = document.getElementById('upload');
---
form.onsubmit = function(event) {
event.preventDefault();
---
---
var xhr = new XMLHttpRequest();
// Open the connection.
xhr.open('POST', 'localhost/uploader', true);
// handler on response
xhr.onload = function () {
if (xhr.status === 200) {
console.log("resp: "+xhr);
console.log("resptxt: "+xhr.responseText);
//somehow load table with xhr.responseText
} else {
alert('ooops');
}
};
// Send the Data.
xhr.send(formData);
So ideally I need one empty row in the table or similar until someone uploads a file and then the table gets populated with the response.
Any help much appreciated.
var xhr1 = new XMLHttpRequest();
xhr1.open('POST', "youruploadserver.com/whatever", true);
xhr1.onreadystatechange = function() {
if (this.status == 200 && this.readyState == 4) {
console.log(this.responseText);
dostuff = this.responseText;
};//end onreadystate
xhr1.send();
It looks mostly correct, You want the this.readyState == 4 in there. what is your question, how to populate a table from the response?
That also depends on how you are going to send the data and how the server is going to parse the data, looks like you want to use a json format which is smart. JSON.stringify(formdata) before you send it and then make sure your server parses it as a json object Using body-parser depending on what server you are using. and then you JSON.stringify() the object to send it back.

AjaxChat: Image Upload code hangs, freezes browser, crashes server

This is a tangent from the question here:
Returning value to Javascript from PHP called from XMLHttpRequest
I am adding an "image upload" button to my AjaxChat. I am using an XMLHttpRequest to send the image to the server, where I run a PHP script to move it to my images folder. Below is the Javascript function in charge of opening the XMLHttpRequest connection and sending the file:
function uploadImage() {
var form = document.getElementById('fileSelectForm');
var photo = document.getElementById('photo');
var uploadButton = document.getElementById('imageUploadButton');
form.onsubmit = function(event) {
event.preventDefault();
// Update button text
uploadButton.innerHTML = 'Uploading...';
//Get selected files from input
var files = photo.files;
// Create a new FormData object
var formData = new FormData();
// Loop through selected files
for (var i = 0; files.length > i; i++) {
var file = files[i];
// Check file type; only images are allowed
if (!file.type.match('image/*')) {
continue;
}
// Add file to request
formData.append('photo', file, file.name);
}
// Set up request
var xhr = new XMLHttpRequest();
// Open connection
xhr.open('POST', 'sites/all/modules/ajaxchat/upload.php', true);
// Set up handler for when request finishes
xhr.onload = function () {
if (xhr.status === 200) {
//File(s) uploaded
uploadButton.innerHTML = 'Upload';
var result = xhr.responseText;
ajaxChat.insertText('\n\[img\]http:\/\/www.mysite.com\/images' + result + '\[\/img\]');
ajaxChat.sendMessage();
} else {
alert('An error occurred!');
}
form.reset();
};
// Send data
xhr.send(formData);
}
}
Here is upload.php:
<?php
$valid_file = true;
if($_FILES['photo']['name']) {
//if no errors...
if(!$_FILES['photo']['error']) {
//now is the time to modify the future file name and validate the file
$new_file_name = strtolower($_FILES['photo']['tmp_name']); //rename file
if($_FILES['photo']['size'] > (1024000)) { //can't be larger than 1 MB
$valid_file = false;
}
//if the file has passed the test
if($valid_file) {
//move it to where we want it to be
move_uploaded_file($_FILES['photo']['tmp_name'], '/var/www/html/images'.$new_file_name);
$message = $new_file_name;
exit("$message");
}
}
}
?>
I currently have the multiple image upload disabled, so the "Loop through selected files" only executes once.
The upload worked for a little bit on my PC, but then I tried uploading an image from my phone. When I did so, the entire server (and my browser) crashed, presumably due to an infinite loop somewhere. Every time I close my browser and log back in, or restart the server, or restart my computer, it hangs and eventually crashes again (on my PC or on my phone). I have been unable to find the script that is causing the issue. I get the feeling it's right under my nose. Does anyone see the problem? If you need the HTML form code then I can provide that, but I don't think it's necessary.

Upload file after javascript processing, no ajax

I am attempting to process a user-uploaded file in javascript and then upload the file to the server. Once the processing is complete, I want the upload to work as it would have if I had not interrupted it with javascript. That is, I want to send a POST request to something like "receive_file.php" where the form validation, move_uploaded_file(), and a "successful upload" message to the user will occur. I have tried this in jquery, and I get an UPLOAD_ERR_NO_FILE from php:
function upload(file) {
var form = $("<form/>", {
enctype: "multipart/form-data",
method: "POST",
action: "/path/to/recieve_file.php"
});
form.append($("<input/>", {
type: "file",
name: "audio_file",
value: file
}));
form.submit();
}
As far as I can tell, its not possible to write to an input type="file", only read from it. Still haven't found a great answer for this one, but what I have settled on is overwriting the current document with the response from an ajax request like so:
var fd = new FormData();
fd.append("audio_file", file);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'recieve.php', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
document.open();
document.write(xhr.response); // just overwrite the whole current document with "recieve.php"
document.close();
}
};
xhr.send(fd);

Categories