AJAX modifying the DOM and calling the function

I am on Linux - both the browser side and the server side - with recent Firefox 38 or 42, if that matters; this one sets more context, and the gythub GPLv3 project contains my code. This is not an ordinary web application (it would usually have one and perhaps a dozen concurrent web users). I am writing or creating server and browser code

Suppose I have HTML5 code like

<div id="mydyndiv_id"></div> 

I am making an AJAX request using jQuery. If successful, it should insert some (HTML element) generated by AJAX, for example. <b>bold</b> (in fact, this is a much larger HTML fragment with nested <span> -s, the contents of which are dynamically generated from the POST argument of the AJAX request), into this div and calls some other Javascript doit function, for example doit(42) only once immediately after an AJAX request (for example, this function will clear some other <textarea> on my page, and argument 42 provided by the AJAX response). I can change the code both on the server side (for example, change the AJAX processing) and on the browser side.

What is the most idiomatic way to achieve this?

  • does an AJAX JSON that contains both the inserted HTML and the function argument, so the AJAX response can be {"text":"<b>bold</b>", "data": 42}" Content-type: "application/json" and the Javascript code will be

      $.ajax ({url: "/someajax", method: "POST", data: {"somearg": "foo"}, datatype: "json", success: function(jsa) { $("#mydyndiv_id").html(jsa.text); doit(jsa.data); }}); 

    it’s quite difficult, the server must double-encode the HTML and JSON HTML fragment: first you need to build the HTML <b>bold</b> fragment, and then build the JSON object and send it.

  • Creating AJAX HTML with some <script> element. The AJAX response will be Content-type: text/html and will contain <b>bold</b><script>doit(42)</script> , and the Javascript code will be

      $.ajax ({url: "/someajax", method: "POST", data: {"somearg": "foo"}, datatype: "html", success: function(ht) { $("#mydyndiv_id").html(ht); }}); 

    this may be wrong, since the doit(42) function can be called more than once and stored in the DOM, and I don’t want

  • Javascript AJAX creation; AJAX response will be Content-type: application-javascript and will contain:

     $("#mydyndiv_id").html("<b>bold</b>"); doit(42); 

    with ajax call in javascript

      $.ajax ({url: "/someajax", method: "POST", data: {"somearg": "foo"}, datatype: "script", success: function(jscode) { /* empty body */ } }) 

    This is a fragile wrt error in doit(42) (see this question ; the only debugging method I have found is a lot of console.log , and this is painful) and also requires double coding on the server side.

Of course, any other technique is welcome!

PS. If you're interested, the code commit a6f1dd7514e5 of the MELT monitor (alpha stage), and you try to use the URL http://localhost.localdomain:8086/nanoedit.html in your browser; this software (which is also a specialized HTTP server!) will have very few simultaneous web users (usually one, perhaps a dozen); in this sense, this is not a regular web application. In my dreams, it can become a workbench for a small team of program developers (C and C ++), and the graphical interface of this toolkit will be their browser.

+2
source share
3 answers

These different approaches have pros and cons, but, as a rule, the first two options are most preferred: see

  • JSON AJAX

    First of all, working with templates on your server is the right approach. If you use this method, you can transfer more flexible data from your server to your client, as you can, for example. use {"text":"<b>bold</b>", "data": 42, "more_data": 43}" .

    You are not required to use only the data at the time the service was originally created, but you can easily transfer the transferred data.

  • HTML AJAX

    This method is simple, and if you want to have a service for each individual piece of data that you need to transfer, rather than serving several parts, this is the preferred choice. Unlike the JSON AJAX method, you cannot extend it here and, if necessary, you will naturally have to create a new service to transfer new data.

  • Javascript AJAX

    Although it’s possible, this method is rather inconvenient, since you cannot support your application in a reasonable way, since your template is a client side. See what Peter-Paul Koch says here:

    Despite the correctness of the solution templates, doing it in a browser is fundamentally wrong. Application maintenance costs should not be unloaded on all users browsers (it said millions of views per month) - especially not mobile ones. This job belongs to the server.

    Further reading: Why the wrong template on the client side .

+1
source

The first approach looks good to me, but it is usually a little ugly to transfer raw HTML through AJAX, if you need to transfer raw HTML, it is better to use PJAX methods, see the jquery-pjax plugin for more information on usage and configuration.

From my point of view, the best approach is to start using jquery-template in order to avoid HTML transfer through AJAX and start transferring only the object that will be displayed to the template on the frontend.Call doit method is approved when processing is successful, until it uses the data provided in answer.

+1
source

I would prefer the option with the first approach. But it depends on the type of generated HTML that you are now returning from the server side.

If this is a simple element, you can simply return the JSON object from the server with one of the properties that identify the element.

For example, a web service response would look like this:

 {'elem': 'b', 'text': 'bold', 'value': '42'} 

And you consume this in an AJAX call like this:

 $.ajax({ datatype: "json", ... success: function(response) { // create the required element client-side var elem = document.createElement(response.elem); // use other properties of the response object elem.textContent = response.text + doit(response.value); // add the element to your div $('#mydiv-1')[0].appendChild(elem); } }); 

Where doit is a Javascript function that is already part of your client code base and you simply use the arguments returned by the web service.


Alternatively, if your generated HTML is a complex piece, you need to define common templates and use client-side templates to convert the returned data into a presentation.

For example, your client template might look like this:

 <script type='text/template' id='tmpl'> <div><h3></h3><p></p><h5></h5></div> </script> 

Your web service returns something like this:

 {'title': 'title', 'text': 'paragraph', 'value': '42'} 

And you consume this in an AJAX call like this:

 $.ajax({ datatype: "json", ... success: function(response) { // clone the client-side template var template = $('#tmpl').html(), $elem = $(template); // append to your div $('#mydiv-2').append($elem); // populate the cloned template with returned object properties $elem.find('h3').text(response.title); $elem.find('p').text(response.text); $elem.find('h5').text(doit(response.value)); } }); 

This way you avoid returning generated HTML from your server and managing presentation data only on the client side. Your web service does not need to know presentation aspects and deals only with raw data (consumption or eruption). The client code receives data from the web service and is engaged in the use and / or presentation of this data as part of the client application.

Demo for both options: https://jsfiddle.net/abhitalks/wuhnuv99/

Bottom line . Do not pass the code. Data transfer. Then the code should use this data.

+1
source

Source: https://habr.com/ru/post/1240727/


All Articles