Skip to content
Michal Čihař edited this page May 16, 2016 · 4 revisions

Generic ajax page loader

Since pma version 4.0 the use of frames has been removed; a new system was therefore necessary to handle the loading of pages while preserving the content in the navigation panel. This has resulted in the introduction of a generic page loader which can be found in 'js/ajax.js'.

There are 3 ways that a page/functionality can be loaded in pma 4.0+.

The generic page loading mechanism

This system will catch clicks on links and submissions of forms and initiate an ajax request, which upon successful completion will replace the content of the current page with the data received in the response.

A custom ajax handler

In this case, a custom js handler function is created that will handle clicks on links and/or the submission of forms. Such a solution is useful when, for example, a page load is not necessary and the required content is loaded in jQuery UI dialog (index editor, rte editor, etc). In order for the generic page loader not to handle such cases, it is necessary to add an "ajax" class to the link or form. E.g:

HTML: click me

JS: $(function(){ // This first line is wrong, more on this below $('a.ajax.anotherclass').click(function (){ // Handle the click event here }); });

Bypassing the page loader

Sometimes it is necessary to leave the browser handle the click/submit event natively. An example here would be the download of a file. In such a case, it is necessary to add a "disableAjax" class to the link/form that we don't want to be handled. E.g:

Export db `foo`

or

` // more tags` ` ` ` ` Another case where the page loader is bypassed is when the href attribute of a link starts with a hash character. E.g:

Click me

If such a link is also handled via JS, it is strongly recommended to make a call to event.preventDefault() in the event handler to avoid setting the hash part of the url to something that cannot be handled by the microhistory plugin (see microhistory section below).

Pitfalls

Expecting the submit button to carry a value

The key/value pair given to a submit button of a form will not be added to the request parameters. This is due to the fact that forms are handled via the $('form').submit() event rather than $('input[type=submit]').click() event, so we don't know which submit button was pressed in order to submit the form.

Example of a bad form:

` ` ` ` ` ` ` ` ` in somepage.php:` ` 1 )` ` ?>`

In order for the above example to work while using the generic page loader, two forms are, in fact, necessary:

` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` #### Reading the wrong array

All forms are submitted via a post request, regardless of what the developer specifies as the method to be used. Example:

` ` ` ` ` ` ` in somepage.php:` ` 1 )` ` ?>`

The onload event

As was mentioned above, since pma 4.0 the pages are almost never fully reloaded, but rather have their content replaced by the results of ajax requests. Furthermore, the script files are only downloaded once, when required, and are then kept in memory in order to minimise network traffic. This presents several issues: 1) The jQuery $(document).ready() event is only fired once after opening pma for the first time, but never again. 2) When registering an onload event we need to know which file it belongs to, so that when a page requires a particular js file, we know which functions to call. 3) We need to be able to destroy registered events, otherwise we will end up registering (and firing) events more than once when we visit the same page more than once.

AJAX.registerOnload

The AJAX.registerOnload function, which can be found in 'js/ajax.js' allows us to register onload event handlers just like $(document).ready(), but it has an extra parameter. E.g:

AJAX.registerOnload( 'db_operations.js', function() { $("#rename_db_form.ajax").live('submit', function(event) { // Some code }); } );

The filename in the first parameter must match exactly the name of the file where this event handler is being registered, excluding the "js/" folder, but including any subfolders. For example, to register an onload event for the 'js/pmd/move.js', the first parameter would be 'pmd/move.js'.

AJAX.registerTeardown

As discussed above, we also need to destroy event handlers when tearing down a page. This is accomplished by calling the AJAX.registerTeardown function. The syntax is quite straightforward:

AJAX.registerTeardown( 'db_operations.js', function() { $("#rename_db_form.ajax").die('submit'); } );

VERY IMPORTANT: 1) You MUST ALWAYS tear down an event handler that you register via AJAX.registerOnload, no exceptions. 2) The selector used to tear down an event handler MUST MATCH exactly the selector used to register the event. Here 'a.class' is not the same as '.class' or 'div > a.class'. 3) You can only use the native jQuery $(document).ready() event for content that will always be on every page (e.g: the navigation panel). And even then you will have to register the event with .live() rather than .bind() as all content on a page will be replaced at some point.

Blacklisting onload/teardown events for files

Sometimes it may not be desirable to register/fire onload/teardown events for a js file (e.g: for some library or jQuery plugin) when it contains no calls to AJAX.registerOnload or AJAX.registerTeardown. In such cases, it is possible to blacklist filenames in 'libraries/Scripts.class.php' in the eventBlacklist function.

/** * Determines whether to fire up an onload event for a file * * @param string $filename The name of the file to be checked * against the blacklist * * @return int 1 to fire up the event, 0 not to */ private function _eventBlacklist($filename) { if ( strpos($filename, 'jquery') !== false || strpos($filename, 'codemirror') !== false /* Add another check, which may even be a regex, here */ ) { return 0; } else { return 1; } }

Accessing common parameters via JS

Before pma 4.0, in order to know which is the current db, the current table, or some other common parameter the developer would access global variables in the top frame context (e.g: window.parent.db). However, as frames have been removed in pma 4.0, this is no longer possible and a new system has been provided as a replacement. This system is contained in the PMA_commonParams module located in 'js/common.js'. Among other methods, it provides a getter and a setter for individual parameters. E.g:

// Getter sample usage var db = PMA_commonParams.get('db'); // Returns the name of the current db var table = PMA_commonParams.get('table'); // Returns the name of the current table // or an empty string if we are not // at table level

// Setter sample usage PMA_commonParams.set('db', new_db_name); PMA_commonParams.set('table', new_table_name);

These are the keys that can be accessed via this module; they are defined in 'libraries/Header.class.php', in the 'getJsParams()' function:

  • collation_connection
  • common_query
  • db
  • lang
  • opendb_url
  • pma_absolute_uri
  • pma_text_default_tab
  • pma_text_left_default_tab
  • querywindow_height
  • querywindow_width
  • safari_browser
  • server
  • table
  • text_dir
  • token

Category:Devel

Clone this wiki locally