Upload image by Froala to server with custom response format - javascript

I am using Froala editor.
I would like to upload images to own server, as described in documentation response format should be { link: 'path/to/image.jpg' }, but my server returns response with another format.
Is it possible to use custom response format with Froala, probably by handle some event?

there is nothing to do with the server response model via the front. its model is designed at backend and if you need to change it you maye parse the Json you get and change the model as you wish. to get the model exactly as you mentioned above you should talk to your backend team.

I'm using cloudinary.com for uploading and serving images and I also have no control on the response. My temporary solution was to monkey patch the JSON.parse method like this (coffeescript) :
var _parseJSON = JSON.parse;
JSON.parse = function(j) {
var response = _parseJSON(j);
response.link = response.secure_url;
return response;
};
I really hope to find a more elegant solution!

Froala seems to not have a mechanism to modify the response from the server when it manages uploads. There is a suitable froala event for this froalaEditor.file.uploaded, but it only can abort the upload process. May be in the future it will be updated to suit such cases
However what you want is absolutely doable. First you'll need to add a query param to imageUploadURL prop in your froala config, e.g. const froalaConfig = {imageUploadURL: '/yourUploadsEndpoint?fromFroala'}. This param is needed to distinguish requests that were actually made by froala from others.
Then we will do a little monkey patch to XMLHttpRequestObject, which is internally used by froala to make http requests:
const accessor = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'responseText')
Object.defineProperty(XMLHttpRequest.prototype, 'responseText', {
get() {
const responseText = accessor.get.call(this)
// here we can check if response url includes our previously set query param
if (this.responseURL.includes('?fromFroala')) {
// r is our response object
const r = JSON.parse(responseText)
return JSON.stringify({ link: <path to your uploaded image url here> })
}
return responseText
},
configurable: true,
})
This should do the trick until froala switches to another data fetching API.

The image.uploaded event is being triggered as soon as there is a response from the server. You could use the response parameter of this event together with the image.insert method to add the image in the editor.
Also, it is important to return false at the end of the callback to prevent the default editor upload chain.
Below is a code snippet for that:
$('.selector')
.froalaEditor()
.on('froalaEditor.image.uploaded', function (e, editor, response) {
// Parse response to get image url.
var img_url = ... ;
// Insert image.
editor.image.insert(img_url, false, null, editor.image.get(), response);
return false;
});

Related

iron-request doesn't make more than one request

I am working with the Polymer 2 library. Whenever I try to make multiple requests using iron-request, the code only ever seems to make a POST request on the first initiation. Any subsequent requests seem to be ignored, even when data that is set to be sent to the server is different from the initial request.
I've written a small example in this Plunker: https://plnkr.co/edit/cozVKUdQ2q2SV46rcCTL?p=preview
I created a iron-request and a button element to initiate the request like so:
<paper-button on-click="save" class="green">Send</paper-button>
...
<iron-request id="xhr"></iron-request>
The save function is setup to take text from a textarea and send that off to a server.
save() {
var response = this.$.xhr.send({
url: "https://httpbin.org/post",
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
body: {
content: this.inputdata
},
method: "POST"
});
var poly = this;
this.$.xhr.completes.then(function(data) {
console.log("finished");
poly.$.responsetext.innerHTML = data.response;
})
The code in question is in the "element1.html" file. If you try sending different text payloads, only the first request will be send. (You can see in the response box that the form "content" field stays the same.)
Any idea what is going on? I'm thinking that I would have to create new iron-request elements everytime I need to make a new request... but that doesn't sound like a very elegant solution.
As you suspected, iron-request has been built to send a single HTTP request. I had a quick look at the its implementation. The send method will actually just return null and not do anything, if the request has a status that is larger 0 than, which will be the case if you have used it before.
While you could create a new iron-request element for each request, it is not elegant (as you said yourself). Instead, you could work with iron-ajax. You can find some instructions on its documentation page.
Your <iron-request> can be rewritten as this.
<iron-ajax id="xhr" url="https://httpbin.org/post" content-type="application/x-www-form-urlencoded" method="POST" body="[[inputdata]]" on-response="onXhrSuccess"></iron-ajax>
Your save function,
save() {
this.$.xhr.generateRequest();
}
onXhrSuccess(event, request) {
console.log("finished");
poly.$.responsetext.innerHTML = event.detail.response;
}

Cannot read the pdf content in the browser with ember

Objective: Display a pdf file, received as a response from server in the new window using ember.
Code in the route file:
actions: {
pdfClick(assessmentId) {
var result = [];
return new Ember.RSVP.Promise(function (resolve, reject) {
Ember.$.ajax({
type: 'GET',
url: 'http://localhost:4200/abc/secured/rest/questions/166',
success: function (data) {
var winlogicalname = "detailPDF";
var winparams = 'dependent=yes,locationbar=no,scrollbars=yes,menubar=yes,' +
'resizable,screenX=50,screenY=50,width=850,height=1050';
var detailWindow = window.open("content-type:application/pdf");
detailWindow.document.write(data);
},
error: function (request, textStatus, error) {
console.log(error);
}
});
});
}
}
Confusion:
var detailWindow = window.open("content-type:application/pdf");
detailWindow.document.write(data);
In the window.open, we are setting the content type as application/pdf and then when we try to write the data (bytestream of PDF file received as a response from the server), junk data appears in the new window.
If I hit the service by Chrome browser, Chrome is able to display the pdf but if I hit the same service with ember ajax, I am not able to display the pdf in the new window.
The problem is about jQuery. jQuery doesn't handle binary data (Reference). While your server is sending binary, you cannot handle this request.
You have different options:
Transporting the binary data by using base64 encryption: Actually I don't like it because of its' overhead.
Using pure XMLHttpRequest instead of jQuery: I've used this in my current project, it works! But too much line of code, hard to track and maintain. Need to wrap with Ember.Promise. My implementation is very close to these answers:1, 2.
Using jQuery transporters: I saw it but haven't use it yet. I don't know whether it is working or not. Here is the reference if you want to look it.

Call a bean method in JavaScript/jquery?

I need to call a bean method in JavaScript and/or jQuery,and have to make decisions depending upon the value returned by method.
How can we do this?
In order for JavaScript and a Java Servlet to be able to talk, as you suggested you will need an AJAX call, which you can do with jQuery.
First, setup a new Servlet which will act as an AJAX web service of sorts. We'll keep it simple, so just implement the doGet() method to handle HTTP GET requests. In that GET method, have a look at the query string for specific arguments.
Example:
myServlet?myArgument1=value1
(Make sure your web.xml maps your Servlet to /myServlet in this example)
Process the request in your Java code (get the value from your bean), then build a JSON response based on that. For instance, you could return:
{ "response": "my value" }
The Java side is done.
On the JavaScript side, you will need to launch a $.getJSON() query.
You would do this in the following way:
var myRequest = $.getJSON("myServlet?myArgument1=" + value1,
function(data)
{
console.log( "success" );
// Process the 'data', which is the JSON response.
var returnedJson = JSON.parse(data);
var value = returnedJson.response; // now equals "my value"
// ...
})
.fail(function()
{
// Handle errors here
console.log( "error" );
})
.always(function()
{
// If you need to do something whether the request was success or fail,
// do it here.
console.log( "complete" );
});
In my opinion that would be the most straightforward way to do it. If you're looking for a Java library that will easily let you parse or create JSON, instead of 'hard-coding' it, you can have a look at json-smart.
https://code.google.com/p/json-smart/

Rendering mongodb database results from POST request in .ajax jquery wrapper in node js

I am creating a basic piece of functionality to allow users to send their location to a server which then queries a database and returns locations near to them. I am using the below jQuery .ajax wrapper to POST data to the server. This takes the form of a latlon point which is then used as the basis for a geosearch in MongoDB using nodejs and express on the backend. The results of the search are then intended to be returned to the client and rendered by the createMapListings function.
The /find page is initially rendered through a GET request to the database via mongodb separate from the below code. However subsequent to initial rendering, I then want to return results dependent on the location provided.
The POST method works fine and the location is posted to the server, with the search results being returned as I can print contents out through the console log.
However, I then want to render the results on the client-side. As mentioned, the results of the search render in the console, but when I attempt to pass through to the client, I can render the data itself (in the form of an array of objects) in the #output div, but the createMapListings function does not seem to catch the data.
In fact, the below function appears to be called but prints out over a thousand rows with the data that should be caught described as 'undefined'. I have tried to use res.render and res.redirect, but in the first case, the view renders in the div (which I suppose is expected) and the redirect fails.
The createMapListings function works fine when a simple GET request is made to the server, for example, for all objects in a collection, using ejs template. However, I think the issue here may be a combination of a POST request and then wanting to pass the results back to the AJAX request using the complete callback.
I apologise if the below code is somewhat obtuse. I’m definitely what you would call a beginner. I appreciate the above functionality may not possible so if there is a better way, I would of course be open to it (res.direct perhaps).
Here is the relevant client side script:
$(document).ready(function(){
$("#geolocate").click(function(){
navigator.geolocation.getCurrentPosition(geolocate, function(){
});
});
});
function geolocate(pos){
var latlonpt = [];
var x = pos.coords.latitude;
var y = pos.coords.longitude;
latlonpt.push(x);
latlonpt.push(y);
var obj = {
userlocation: latitudelongitudept
};
$.ajax({
url: "/find",
type: "POST",
contentType: "application/json",
processData: false,
data: JSON.stringify(obj),
complete: function (data) {
$('#output').html(data.responseText);
$('#infooutput').children().remove();
createMapListings(data.responseText);
}
});
};
function createMapListings(maps) {
for (var i = 0; i < maps.length; i++) {
var url = maps[i]._id;
var fullurl = "<a href='/show?id=" + url + "'>Route</a></div>";
var title = "<div>" + maps[i].title + " - " + fullurl +"";
$('#infooutput').append(title);
};
};
</script>
Here is the relevant route used in a basic express app to handle the post request made by the above .ajax wrapper.
exports.findbylocation = function(req, res) {
console.log(req.body.userlocation);
var userlocation = req.body.userlocation;
Map.ensureIndexes;
Map.find({loc :{ $near : userlocation }}, function(err, maps) {
if (err) {
console.log(err)
}
else {
var jmaps = JSON.stringify(maps);
console.log(jmaps);
res.send(jmaps);
}
});
};
By convention, the data variable name in an $.ajax callback signature refers to the parsed HTTP response body. Since your callback is on complete, we're actually passed the XMLHttpRequest used, by convention called xhr. You rightly grab the responseText property, but this needs parsing to be useful. So long as we take care over our Content-Type's and don't explicitly disable processData, jQuery will do the encoding/unencoding for us - we just deal with objects. This is a good thing, since the transport format isn't usually of any particular importance to the application logic. If we use res.json(maps) in place of res.send(jmaps), we can write our call more simply:
$.ajax({
url: '/find',
type: 'POST',
data: obj,
success: function(data) {},
error: function(xhr, text, err) {}
});
Here data is a Javascript object already parsed and ready to use. We also use a default application/x-www-form-urlencoded request rather than explicitly setting a contentType. This is the same as far as express is concerned: it will just be parsed by urlencoded instead of json.
Assuming you solved your client-sie problem.
As you are using express there is no need for JSON.stringfy,
you can use res.json(maps).

What is the best design pattern for asynchronous message passing in a Chrome extension?

I have a background script that is responsible for getting and setting data to a localStorage database. My content scripts must communicate with the background script to send and receive data.
Right now I send a JSON object to a function that contains the command and the data. So if I'm trying to add an object to the database Ill create JSON that has a command attribute that is addObject and another object that is the data. Once this is completed the background scripts sends a response back stating that it was successful.
Another use case of the function would be to ask for data in which case it would send an object back rather than a success/fail.
The code gets kind of hacky once I start trying to retrieve the returned object from the background script.
It seems like there is probably a simple design problem to follow here that I'm not familiar with. Some people have suggested future/promise design problems but I haven't found a very good example.
Content Script
function sendCommand(cmdJson){
chrome.extension.sendRequest(cmdJson, function(response){
//figure out what to do with response
});
}
Background script
if (request.command == "addObject"){
db[request.id]= JSON.stringify(request.data);
sendResponse("success");
}
else if(request.command == "getKeystroke"){
var keystroke = db[request.id];
sendResponse(keystroke);
}
Your system looks OK and here are some minor improvements.
For each remote command send back the same type of object (with possibly empty fields):
var response = {
success: true, // or false
data: {},
errors: [],
callback: ''
}
Also, if you have multiple different commands which send back data, you may replace if-else with an object lookup:
var commands = {
addObject: function () { /* ... */ },
getKeystroke: function (request, response) {
response.data = db[request.id]
}
}
Then if you have any data to response with, just add it to the object. And send the same object for any command:
var fn = commands[request.commands]
fn(request, response)
As for figuring out what to do with response, I'd pass a callback into the sendCommand function and let the content scripts request and process the response data as they see fit:
function sendCommand(cmdJson, callback){
chrome.extension.sendRequest(cmdJson, callback)
}

Categories

Resources