====== Create an Ajax service ====== ===== What is an Ajax service? ===== An Ajax service collects and returns data as an XML file. This service will be called dynamically via an Ajax request and will be processed by some Javascript to update a part of a Doctlear administration page. This is, for instance, what is used to display the list of tags when writing a post. When clicking __//See all tags//__ link, the associated Ajax service is called, returns the list of tags, and this list is displayed to the user. ===== Prerequisites ===== To create an Ajax service, you will need to: * Create a public and static PHP function. This function will be the one returning the expected results. * Declare the new service to Dotclear. * Call the service and process the data using Javascript. In the following part, we will create a service to dynamically display, on the post creation page, the time left before a scheduled post is put online. ===== Service creation ===== The function name will be the service identifier. Be careful not to choose a name that is already used by another service. In our case, we will call it //getPostRemainingTime//. As a convention, we will write our services code in the [[files#general-organization-of-a-plugin|_services.php]] file, in the plugin root. If you wish to use several services, they can all be written there. To retrieve the wanted information, we need the current post ID. We will get it using the **id** parameter that is passed in the URL. We also need the $core object to retrieve the post associated to this ID. In order to do this, we will use the parameters of the method defined earlier: $id = isset($get['id']) ? $get['id'] : null; $rs = $core->blog->getPost(array('post_id' => $id)); $date = strtotime($rs->post_dt); # Time difference (in seconds) between now and the publication date $delta = $date - time(); Now we have the information we need, it is possible to manipulate it to use the format we want. We can for instance pass the format we want as a parameter in the URL and convert the $delta accordingly. After that we have to return this data as an XML. For this, Dotclear has a special //xmlTags// class allowing to create this kind of structure very easily. As a convention, our responses will be encapsulated in a //rsp// node: # Creation of the wrapper $rsp = new xmlTag(); # Add the "value" node in the "rsp" node containing the $delta variable $rsp->value($delta); # Return everything return $rsp; The generated XML file will look like this: 65765432456 It is possible to add attributes to the node, and to combine them. For more details, you can check the other plugins using this system, or you can check Dotclear itself! ===== Service declaration ===== Dotclear uses its own generic service dispatcher in the //services.php// file. To use it, the service has to be declared to Dotclear using the following method: $core->rest->addFunction('getPostRemainingTime',array('myPluginRestMethods','getPostRemainingTime')); This code has to be put in the plugin [[files#general-organization-of-a-plugin|_prepend.php]] file. Now our service is declared, we can access it throught the **//ADMIN_URL/services.php?f=getPostRemainingTime&id=1//** URL. Check if it works correctly before going further. Don't forget to load the **_services.php** file **before** declaring the service. ===== Data processing ===== We will now go through the //Ajax// part of the service. The Javascript shown here will allow us to request data to the service and to display the response in the page without reloading it. We are going to use //jQuery//, which is bundled with Dotclear: $(function(){ $('#remaining-time').click(function(){ $.get('services.php', {f: 'getPostRemainingTime',id: $('#id').val()}, function(rsp){ $('#remaining-time-display').html('

Remaining time before online publishing:'+$(rsp).find('value').text()+'

'); }); }); });
When clicking on the element with ID **remaining-time**, a request is made to the **getPostRemainingTime** service, passing the service we want to use and the current post ID (retrieved using the hidden **id** field of the form) as parameters. The response is displayed in the block with ID **remaining-time-display**. ===== Error handling ===== The code above does not handle errors that may happen when requesting the service. The advantage of using the //xmlTags// class to generate the XML is that if an exception is raised, the returned XML will look like: Exception message For instance, for our service, if no ID is passed in parameter, we will raise an exception to inform the user: $id = isset($_GET['id']) ? $_GET['id'] : null; if ($id === null) { throw new Exception(__('No ID given')); } It is therefore very easy to catch this kind of XML to handle it differently. For instance: $(function(){ $('#remaining-time').click(function(){ $.get('services.php', {f: 'getPostRemainingTime',id: $('#id').val()}, function(data){ var rsp = $(data).children('rsp')[0]; if (rsp.attributes[0].value == 'ok') { $('#remaining-time-display').html('

Remaining time before online publishing:'+$(rsp).find('value').text()+'

'); } else { alert($(rsp).find('message').text()); } }); }); });
This code will inform the user through an //alert()// message that an error appeared when requesting the service, or during the service processing.