Home Links
Home Page
Use XML in PHP
Compression of the data on PHP
Use mod_perl
Style of coding on PHP
Perl and XML. Library of the programmer
Access to databases under management SUBD POSTGRES95
Parsing on Perl
XMLHttpRequest (AJAX) - sending and processing of answers of http-searches with help JavaScript.
Subsys_JsHttpRequest: pumping of the data without perezagruzki pages (AJAX)
The brief description of regular expressions: POSIX and PCRE
Optimization of searches in MySQL
Wound of treelike structures in Databases (Nested Sets)
Oracle / PHP FAQ
The specification and functions DOM in PHP
Not kehshirovat`!
Report PPP
Useful advice{councils} on optimization of ASP-applications
XML: time has come
 

Subsys_JsHttpRequest: pumping of the data without perezagruzki pages (AJAX)

Not so long ago the certain popularity was received with new service Google: so-called Google Suggest. Those who yet did not see, what is it such, can see right now: http: // www.google.com/webhp? complete=1*hl=en.



Job Google Suggest consists that under the several entered letters the special program on JavaScript addresses to site Google and requests of him  10 most "popular" words beginning with the same letters. The script works so quickly, that the dropping out list with variants appears practically instantly. Naturally, perezagruzka pages thus it is not made - all is realized on JavaScript and DHTML.


For realization « dynamic podgruzki » Google uses the following means:


1. In Internet Explorer: a ActiveX-component with name Msxml2. XMLHTTP or Microsoft. XMLHTTP.

2. In Mozilla and FireFox: built - in class XMLHttpRequest.

3. In Opera: dynamically created the zero size (latent).


How works Google Suggest, in the Internet write everyone to whom not laziness, and I am not going to repeat at all. Instead of it I shall present{introduce} the new approach under name Subsys_JsHttpRequest, bypassing Google Suggest on compatibility with various browsers.

Lacks of approach Google Suggest


So, in different browsers Google applies completely various methods podgruzki. We shall consider their lacks.


1. Since in IE it is used a ActiveX-component, you should switch on ActiveX in adjustments of a browser. And though by default given function just is switched on, many users, naslyshannye about numerous holes IE, manually disconnect her .

Lyrical digression


Despite of it, all of you can be convinced, that Google Suggest continues to work and after deenergizing ActiveX. Probably, the mechanism based on (as in Opera) will be involved. In any case, on your sites Microsoft. XMLHTTP at switched off ActiveX will not work (it is checked up). About lacks of a method it is said below.

2. Class XMLHttpRequest used in Mozilla and FireFox, at the moment is present only at these browsers (support of this class in Opera 8.01 is rather limited). He  has small lack: at umolchatel`nykh adjustments FireFox it is forbidden to load the data whence, except for as from the current site.

3. Application dynamically created is connected to weight of problems. The main lack - at change of attribute src at is distributed characteristic click and recording in « a history of a browser » so button Back starts to work incorrectly (Back) is added. And though given "reef" can be bypassed (rather artificial way), arise new problems, various in different browsers. I shall not list{transfer} them now; I shall say only, that for 2 days has tried set (pieces 20) every possible variants, but to achieve krossbrauzernogo a code working equally and without extraneous effects in all browsers, and it was not possible to me. Other lack - the big charge of memory and a sluggishness: actually, for each frame the new separate browser which independently processes the loaded HTML-code is created.


To put it briefly, Google uses different (orthogonal, incompatible) approaches in various browsers.


The method which realizes dynamic podgruzku in Google Suggest, is illustrated below by the example of loading the initial text of the current page. (with I here do not bring Job, because she is rather complex . The question is only class XMLHttpRequest and ActiveX-component Microsoft. XMLHTTP).



<script>

function doLoad () {

  var req = window. XMLHttpRequest?

    new XMLHttpRequest ():

    new ActiveXObject (" Microsoft. XMLHTTP ");

  req.onreadystatechange = function () {

    if (req.readyState == 4)

      alert ('Loaded:n' +req.responseText);

}

  req.open ("GET", document.location, true);

  req.send (null);

}

</script>

<input type = "button" value = " Show me " onclick = " doLoad () ">


This code will work only in Mozilla (FireFox), and also in IE (at switched on ActiveX). Opera 7.x, and also the users, switched off to themselves ActiveX for safety reasons, "have a rest".



Principle of job Subsys_JsHttpRequest


With ActiveX, XMLHttpRequest also it is possible to avoid numerous problems and features, if... To not use the given technologies. It sounds is really banal, however - works!


The matter is that there is one perfect and more - less krossbrauzernyj a way of loading of the data on page. It is very strange, that developers Google up to him  have not guessed. Speech about dynamic creation and connection to the current page of a tag. Such tag should specify attribute src, conterminous with the address of a server script podgruzki the data (written, for example, on PHP).

Teapot


Certainly, the loaded script should give out a correct code on JavaScript. The usual text such method not podgruzish`.


Let's consider on an example as the given approach works. We shall assume, that by pressing the button the JavaScript-program inserts (c use DHTML) into the current page the following tag:



<script language = "JavaScript"

src = " load.php? ff=ok*opera=sucks*123 "> </script>


What thus will take place? The browser will immediately address to the server with the following search:


Listing 3 to copy a code in a clipboard



load.php? ff=ok*opera=sucks*123


In result on the server the script load.php which will receive in QUERY_STRING parameters ff=ok*opera=sucks*123 (certainly will be started, arguments can be any). The program will fulfil (for example, will address to a database) and will print as resulting page the following text:


Listing 4 to copy a code in a clipboard



Subsys_JsHttpRequest_Js.dataReady (

  123,

  [

    ' It is some data. ',

    ' They can have any structure... ',

    {test: '... And an enclosure '}

],

  ' And here there is a simple debugging text. '

)


If you have not understood, to what all these square and braces, read thirty eighth nablu in which features of syntax JavaScript are considered{examined} more likely.


So, the PHP-script load.php has printed the text being in combination the correct JavaScript-program in the target stream. He will be used by a browser as a source of the data of any structure.


o-mmm... « The program writing other programs »... "Source"... Definitely « Matrix has you ».


In a result the code on JavaScript, generated by a PHP-script load.php, will be executed by a browser! As you can see, the method dataReady () object Subsys_JsHttpRequest_Js to which it is passed is caused:


1. The unique identifier of loading (to not confuse one data with others, in fact the page can request simultaneously data at once from several sources).

2. The any data received by the program load.php, for example, from a DB.

3. Some text which can be used in the debugging purposes (for example, there it is convenient to specify the error messages, arisen in the PHP-program).


Well and function Subsys_JsHttpRequest_Js.dataReady () cares of delivery zagruzhenykh given to the end user, carrying out also caching of identical searches (if it is authorized).


Dynamic generation of a tag <SCRIPT> has one important advantage: at use of such approach "history" of a browser (history) does not get littered with superfluous links, and at loading it is not audible the click issued by many browsers during transition to other page. It is necessary to notice also, that in FireFox there is a small mistake as a result of which the status - line is not cleared after loading <SCRIPT> a component (in her there is a message " Loading... "). However, this mistake on anything does not influence and, probably, will be shortly corrected by developers.


Library Subsys_JsHttpRequest will consist of two parts working in common with each other:


* Subsys/JsHttpRequest/Js.js, 8 KB: a JavaScript-code determining class - object Subsys_JsHttpRequest_Js. It - so-called frontend systems (« forward pass »). It{he} should be connected to pages with the help of a tag:


Listing 5 to copy a code in a clipboard



<script language = "JavaScript" src = "Subsys/JsHttpRequest/Js.js">

      </script>


* Subsys/JsHttpRequest/Php.php, 10 KB: a PHP-code in which functions for simplification of a spelling of loaders on PHP are defined{determined}. It - so-called backend systems (« back pass »). It{he} should be included in the beginning of the program the operator:


Listing 6 to copy a code in a clipboard



require_once "Subsys/JsHttpRequest/Php.php";


As language for a spelling of loaders it is chosen PHP, because he:


* It is rather distributed.

* It is fastest, if it is necessary to work with small scripts, koimi just and loaders are. (It, naturally, concerns only mod_php - he so more often and is put khosterami.)

* In most cases has built - in support Unicode (expansion iconv) which as you will see below, very much is required to us.


It is possible to write, certainly, scripts of loading and on CGI-perl, however in this case loading on the server will sharply increase, that for dynamic podgruzki the data is contra-indicated. Well and mod_perl you will meet far from being on each hosting.

Class Subsys_JsHttpRequest_Js: frontend


To use object Subsys_JsHttpRequest_Js in the JavaScript-program it is absolutely simple. Actually, his  interface practically does not differ from interfaces FireFox-ovskogo XMLHttpRequest or IE-shnogo Microsoft. XMLHTTP (he specially so was developed).


I shall result an example of page which provides generation of khehsh-code MD5 for the line entered by the user. Calculation occurs on the server, and the browser only addresses to the last for the data, using object Subsys_JsHttpRequest_Js. (the Same example in operation.)


Listing 7 to copy a code in a clipboard



<? php

// Check of job with sessions.


session_start ();

$ _SESSION ['hello'] = ' Backend loaded at '.date ('r');

?>

<html>

<head> </head>

<body>


<script language = "JavaScript"

src = "../../../lib/Subsys/JsHttpRequest/Js.js "> </script>

<script>

    // It is caused on a time-out or at click on the button.


    function doLoad (force) {

        // We receive the text of search from <input> fields.


        var query = " + document.getElementById ('query') .value;

        // We create new object JSHttpRequest.


        var req = new Subsys_JsHttpRequest_Js ();

        // A code automatically caused at the termination{ending} of loading.


        req.onreadystatechange = function () {

            if (req.readyState == 4) {

                if (req.responseJS) {

                    // We write down in <div> result of job.


                    document.getElementById ('result') .innerHTML =

                        ' MD5 (" ' + (req.responseJS.q || ") + ' ") = ' +

                        '"' + (req.responseJS.md5 || ") + ' " <br> ' +

                        ' Session data: ' +

                        ' " ' + (req.responseJS.hello || ' unknown ') + ' " ';

}

                // The debugging information.


                document.getElementById (' debug ') .innerHTML =

                    req.responseText;

}

}

        // We resolve caching (that at identical searches


        // To not address to the server some times).


        req.caching = true;

        // Podgotvalivaem object.


        req.open (' POST ',' load.php? test=abc ', true);

        // We send the data of search (are set as khehsha).


        req.send ({q: query, test:303});

}

    // Support of loading of the data on a time-out (1 second after


    // The last otpuskanija keys in a text field).


    var timeout = null;

    function doLoadUp () {

        if (timeout) clearTimeout (timeout);

        timeout = setTimeout (doLoad, 1000);

}

</script>

<! - the Form->

<a href = " <? = $ _ SERVER [' REQUEST_URI ']?> "> Reload myself </a>

<form onsubmit = " return false ">

    <input type = "text" id = "query" onkeyup = " doLoadUp () ">

    <input type = "button" onclick = " doLoad (true) " value = "load">

    <br> <i> Enter "error" to test debugging opportunities of library. </i>

</form>

<! - Results of job (it is filled dynamically)->

<div id = "result" style = " border:1px solid *000; margin:2px ">

    Results

</div>

<! - the Debugging information (it is filled dynamically)->

<div id = "debug" style = " border:1px dashed red; margin:2px ">

    Debug info

</div>


</body>

</html>

<hr>

<? show_source (__ FILE __)?>


Because of an abundance of comments looks if closely{attentively} to see, however, terribly, it is well visible, that application Subsys_JsHttpRequest_Js anything basic does not differ from use XMLHttpRequest or Microsoft. XMLHTTP.


There is one important feature of library: the result of job load.php is convenient for receiving from property req.responseJS. Apparently, in him  the loader places the following khehsh:


Listing 8 to copy a code in a clipboard



{

  q: ' Search ',

  md5: ' a MD5-code of the entered line '

}


The data given by a script load.php in the target stream are stored{kept} in a field req.responseText (by operators echo). In most cases they contain only error messages (if mistakes took place) and for this reason the given property is treated as debugging.


Lyrical digression


However, nothing prevents to write the loader so that he passed the basic result of the job as req.responseText (though it and is not so convenient - see below).



Class Subsys_JsHttpRequest_Php: backend


Now there has come time to see, as the loader load.php looks. Remember, we spoke, that result of his  job should be the text being a correct JavaScript-code. I.e. simply to deduce{remove} " Greetings, these are the generated data! " It is impossible - it is necessary "to wrap up" in the beginning their call of function Subsys_JsHttpRequest_Js.dataReady (). You can think: how much trouble arises because of it... In fact it is enough to commit one small mistake (for example to pass{miss} a point) as the resulting code will cease to be correct while the loader will not give out any mistake.


But look at a code of the loader. You will see, that all problems described above in him simply do not arise! (the Same PHP-script.)


Listing 9 to copy a code in a clipboard



<? php

//


// ATTENTION! Before connection of library in a browser should not be deduced{removed}


// Any symbol. Otherwise function header (), used


// Library, will not work (see the documentation), and there will be a mistake.


//



// We shall start session.


session_start ();

// We connect library of support.


require_once "../../../lib/config.php ";

require_once "Subsys/JsHttpRequest/Php.php";

// We create the main object of library.


// We specify the coding of page (necessarily!).


$JsHttpRequest = and new Subsys_JsHttpRequest_Php ("windows-1251");

// We receive search.


$q = $ _REQUEST [' q '];

// We form result directly as a PHP-file!


$ _RESULT = array (

  "q" => $q,

  "md5" => md5 ($q),

  ' hello ' => isset ($ _SESSION [' hello '])? $ _SESSION [' hello ']: null

);

// Demonstration of debugging messages.


if (strpos ($q, ' error ')! == false) {

  callUndefinedFunction ();

}


echo " <b> REQUEST_URI: </b> ". $ _SERVER [' REQUEST_URI ']. " <br> ";

echo " <b> Loader used: </b> ". $JsHttpRequest-> LOADER;

?>


So, library Subsys_JsHttpRequest_Php incurs all « dirty job » on "obertyvaniju" result of job of the loader in a JavaScript-code. In the program it is enough to appropriate{give} only value to a special file $ _RESULT, and the data, due to harmonious job frontend-and backend-parts of library, will safely enter a browser, having saved the structure.


Fortunately, files both khehshi JavaScript and PHP are arranged practically equally, therefore it is possible to make translation of a PHP-file without serious consequences...


Listing 10 to copy a code in a clipboard



$ _RESULT === array (

  "q" => ' search ',

  "md5" => ' a MD5-code of the entered line '

)


... In JavaScript-khehsh:


Listing 11 to copy a code in a clipboard



req.responseJS === {

  q: ' Search ',

  md5: ' a MD5-code of the entered line '

}


Well and that all has finally cleared up, I shall result provisional result of job of a script load.php as it{he} is seen with a browser (already after "obertyvanija" library Subsys_JsHttpRequest_Php):


Listing 12 to copy a code in a clipboard



Subsys_JsHttpRequest_Js.dataReady (

  123,

  ' Debugging messages. ',

  {

    q: ' Search ',

    md5: ' a MD5-code of the entered line '

}

)


So, simple giving of value to a file $ _RESULT results in generation of such JavaScript-code. He simply physically cannot appear incorrect (for it is always created on an identical pattern, and inverted commas with apostrophes in him are shielded by backend-part Subsys_JsHttpRequest_Php).

Interception of mistakes in the PHP-loader


"Obertyvanie" works with use of function PHP ob_start () which allows to intercept the data acting in a target stream of a script, and to make with them any transformations. By a lucky chance, ob_start () allows to intercept also the mistakes which have occurred in a script, including fatal, not giving in to interception by any other ways!


By the way, this useful feature of function ob_start () is rather little-known. You can use her  and for other purposes - for example that is guaranteed to deduce{remove} the bottom part of page even in case of serious crash of a script.


Since all error messages (for example, a call of nonexistent function) PHP prints directly in a target stream (as if through echo), it is logical to perceive all contents of a target stream of a script as the debugging text. If you remember, this text is accessible in property req.responseText, empty at correct end of the loader. Due to the mechanism "obertyvanija" any, even the most serious, the mistake in the PHP-program will not generate an incorrect JavaScript-code. Instead of it the text of a mistake will get in the third parameter of function Subsys_JsHttpRequest_Js.dataReady (), and in a result appears in req.responseText.


You can be convinced, that interception of mistakes works, having entered on test page (is (see higher) a line containing a word "error". You receive the message in the bottom dynamic field:


Listing 13 to copy a code in a clipboard



Fatal error: Call to undefined function: callundefinedfunction ()

in load.php on line 15



The decision of a problem with codings


At formation of search to the loader it can be demanded to pass him the lines containing Russian letters. Naturally, they cannot be passed directly in URL, and in the beginning it is necessary to URL-code - to transform each symbol of Russian alphabet to a kind %XX, where XX - a code of a symbol.


In JavaScript there is a function escape () which URL-codes a line of the data. Unfortunately, she returns result only as Unicode. For example, the line "test" is represented to her so "%u043F%u0440%u043E%u0431%u0430". In PHP there are no the functions, able to decode such data presentation (urldecode () here the bad assistant for she does not support a format %uXXXX). Function escape () allows to code any symbol, whether it be Russian letter, a letter of the Greek alphabet or even a Chinese hieroglyph.


Lyrical digression


Generally speaking, in last versions JavaScript is present function encodeURIComponent (), able to code the data around Unicode. However she is not supported, for example, in Internet Explorer 5.0 so from a reason krossbrauzernosti to us does not approach.


Fortunately, popular expansion iconv for PHP supports function for transformation of the data to every possible codings so to recode from Unicode in Windows-1251 does not make for backend-library Subsys_JsHttpRequest_Php of special complexities.


Lyrical digression


At numerous requests, since version 3.0 library Subsys_JsHttpRequest_Php can work and without iconv if the basic coding of a site is windows-1251 or koi8-r. Functions and tables of translation from Unicode in one of these one-byte codings are built - in the module.


So, you can cause a method send () object Subsys_JsHttpRequest_Js, not reflecting about codings of the data. You do not need to recode anything manually neither in server, nor in a client code: the library takes all this job on itself.


Once again: if you want to use library Subsys_JsHttpRequest with the codings which are distinct from windows-1251 and koi8-r (for example, with UTF-8), on the server expansion PHP iconv should be established. At the majority khosterov it costs{stands}, but if suddenly appears, that no (to a shame of the provider), khosteru the module is possible to establish it .

That new in version 3.0


Early versions of library (1.x and 2.x) were called JSHttpRequest. They possessed a little smaller functionality, than Subsys_JsHttpRequest. The new version - 3.x - supports the following opportunities inaccessible to its{her} progenitrix:


* If the browser has built - in object XMLHttpRequest or ActiveX-element Msxml2. XMLHTTP/Microsoft. XMLHTTP, and thus there are no problems with safety (the reference{manipulation} to the loader on the same domain), they will automatically be involved. Otherwise - the method of dynamic creation of an element <SCRIPT> is used.

* In a mode of use XMLHttpRequest (or corresponding ActiveX) the method of sending of search POST (it is underlined by a call open ()) is supported. However, if with POST arise problems (for example, in Opera 8.01), the library is automatically switched to standard method GET. This occurs, when XMLHttpRequest is not supported by a browser - mistakes in any case is not given out.

* URL the loader, transmitted to a method open (), now can contain parameters (for example, load.php? test=abc).

* Parameters now are passed in QUERY_STRING by completely usual way traditional for PHP-and CGI-scripts. Typical URL search to the loader: load.php? test=abc*q = % u043F%u0440%u043E%u0431%u0430*4. Here:

1. load.php? test=abc - the address of the loader specified in a method open ().

2.*4 - the "harmless" additive, sodezhahhaja ID sessions of loading (it is unique for each search).

3. q = % u043F%u0440%u043E%u0431%u0430 - the parameters transferred{handed} in a method send ().

* Standard sessions PHP are completely supported, and backend libraries Subsys_JsHttpRequest_Php about them « knows nothing », passing powers of management of sessions to interpreter PHP. Parameter PHPSESSID specified either in kukakh, or in GET, is passed frontend-ohm Subsys_JsHttpRequest_Js to the PHP-loader (in addition to usual GET-parameters). Accordingly, if the script - frontend has established any variables in session, the loader - backend can read them standard means.

* Parameters (in a method send ()) can be passed the loader in the standard PHP-form (for example, with names a [abc], b [xyz], etc.). I.e. analysis QUERY_STRING - on shoulders of standard functions PHP, instead of goes manually, as in the previous version.

* In case the base coding of a site - windows-1251 or koi8-r, and expansion iconv in PHP is not connected, own function of code conversion is used. So in overwhelming majority of cases library it will be correct to work with Russian letters even at absence iconv!


Still big krossbrauzernost`?


I have big suspicion, that the trick with dynamic generation of a tag <SCRIPT> would work and in other, older versions of browsers (at least, in IE4). However in this case the code of library any more would not be such universal - it should "to become attached" to features of browsers. Besides old versions do not support DOM up to the mark (functions getElementById (), createElement mean (), appendChild (), etc.) while class Subsys_JsHttpRequest_Js uses exclusively DOM. In IE, for example, it would be possible to use document.all and prisavivanija values to property innerHTML some element.


If you decide to modify library so that she worked and in old browsers, I shall be glad to receive from you the changed code, and also to discuss his  nuances in a forum.

The resume


Let's sum up this big emb. In the beginning I shall list links to the program modules mentioned above.


* JavaScript-frontend libraries Subsys_JsHttpRequest_Js: Subsys/JsHttpRequest/Js.js.

* PHP-backend libraries Subsys_JsHttpRequest_Php: Subsys/JsHttpRequest/Php.php.


Example of use of library:


* All examples from clause{article} (zip).

* A client code (JavaScript): test.htm.

* A server code of the loader (PHP): load.php.


Library Subsys_JsHttpRequest is actively used at a forum forum.dklab.ru. Namely, through it{her} the following functions are realized:


* " Alive search ": on each page of a forum there is a field into which it is possible to enter search search and at once to receive result, passing perezagruzku pages.

* " Alive search " in the form of addition new topika: the same, but works at input of a subject of the new message.

* " The Alive preview ": near to links on topiki the special icon is resulted, having guided the mouse on which, it is possible to see{overlook} the first message topika.

* " Alive karma ": users can change karmu (rating) to each other, not reloading page.