Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
D
drupal
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Custom Issue Tracker
Custom Issue Tracker
Labels
Merge Requests
315
Merge Requests
315
Requirements
Requirements
List
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Analytics
Analytics
Code Review
Insights
Issue
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
project
drupal
Commits
5e32593f
Commit
5e32593f
authored
Mar 13, 2010
by
Dries
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Patch
#716602
by effulgentsia: refactor ajax_render() and clean up 'ajax' element type.
parent
1106db64
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
101 additions
and
89 deletions
+101
-89
includes/ajax.inc
includes/ajax.inc
+69
-50
modules/book/book.pages.inc
modules/book/book.pages.inc
+2
-9
modules/field/field.form.inc
modules/field/field.form.inc
+1
-1
modules/file/file.module
modules/file/file.module
+3
-3
modules/simpletest/tests/ajax_forms_test.module
modules/simpletest/tests/ajax_forms_test.module
+14
-14
modules/simpletest/tests/ajax_test.module
modules/simpletest/tests/ajax_test.module
+8
-10
modules/system/system.module
modules/system/system.module
+4
-2
No files found.
includes/ajax.inc
View file @
5e32593f
...
...
@@ -166,9 +166,10 @@
* $commands[] = ajax_command_replace('#object-1', 'some html here');
* // Add a visual "changed" marker to the '#object-1' element.
* $commands[] = ajax_command_changed('#object-1');
* // Output new markup to the browser and end the request.
* // Note: Only custom AJAX paths/page callbacks need to do this manually.
* ajax_render($commands);
* // Menu 'page callback' and #ajax['callback'] functions are supposed to
* // return render arrays. If returning an AJAX commands array, it must be
* // encapsulated in a render array structure.
* return array('#type' => 'ajax', '#commands' => $commands);
* @endcode
*
* When returning an AJAX command array, it is often useful to have
...
...
@@ -178,28 +179,20 @@
* $commands = array();
* $commands[] = ajax_command_replace(NULL, $output);
* $commands[] = ajax_command_prepend(NULL, theme('status_messages'));
* return
$commands
;
* return
array('#type' => 'ajax', '#commands' => $commands)
;
* @endcode
*
* See @link ajax_commands AJAX framework commands @endlink
*/
/**
* Render a commands array into JSON and exit.
*
* Commands are immediately handed back to the AJAX requester. This function
* will render and immediately exit.
* Render a commands array into JSON.
*
* @param $commands
* A list of macro commands generated by the use of ajax_command_*()
* functions.
* @param $header
* If set to FALSE the 'text/javascript' header used by drupal_json_output()
* will not be used, which is necessary when using an IFRAME. If set to
* 'multipart' the output will be wrapped in a textarea, which can also be
* used as an alternative method when uploading files.
*/
function
ajax_render
(
$commands
=
array
()
,
$header
=
TRUE
)
{
function
ajax_render
(
$commands
=
array
())
{
// Automatically extract any 'settings' added via drupal_add_js() and make
// them the first command.
$scripts
=
drupal_add_js
(
NULL
,
NULL
);
...
...
@@ -210,36 +203,7 @@ function ajax_render($commands = array(), $header = TRUE) {
// Allow modules to alter any AJAX response.
drupal_alter
(
'ajax_render'
,
$commands
);
// Use === here so that bool TRUE doesn't match 'multipart'.
if
(
$header
===
'multipart'
)
{
// We do not use drupal_json_output() here because the header is not true.
// We are not really returning JSON, strictly-speaking, but rather JSON
// content wrapped in a textarea as per the "file uploads" example here:
// http://malsup.com/jquery/form/#code-samples
print
'<textarea>'
.
drupal_json_encode
(
$commands
)
.
'</textarea>'
;
}
elseif
(
$header
)
{
drupal_json_output
(
$commands
);
}
else
{
print
drupal_json_encode
(
$commands
);
}
drupal_exit
();
}
/**
* Send an error response back via AJAX and immediately exit.
*
* This function can be used to quickly create a command array with an error
* string and send it, short-circuiting the error handling process.
*
* @param $error
* A string to display in an alert.
*/
function
ajax_render_error
(
$error
=
''
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_alert
(
empty
(
$error
)
?
t
(
'An error occurred while handling the request: The server received invalid input.'
)
:
$error
);
ajax_render
(
$commands
);
return
drupal_json_encode
(
$commands
);
}
/**
...
...
@@ -368,6 +332,10 @@ function ajax_form_callback() {
*/
function
ajax_deliver
(
$page_callback_result
)
{
$commands
=
array
();
$header
=
TRUE
;
// Normalize whatever was returned by the page callback to an AJAX commands
// array.
if
(
!
isset
(
$page_callback_result
))
{
// Simply delivering an empty commands array is sufficient. This results
// in the AJAX request being completed, but nothing being done to the page.
...
...
@@ -388,11 +356,20 @@ function ajax_deliver($page_callback_result) {
break
;
}
}
elseif
(
is_array
(
$page_callback_result
)
&&
isset
(
$page_callback_result
[
'#type'
])
&&
(
$page_callback_result
[
'#type'
]
==
'ajax_commands'
))
{
// Complex AJAX callbacks can return a result that contains a specific
// set of commands to send to the browser.
if
(
isset
(
$page_callback_result
[
'#ajax_commands'
]))
{
$commands
=
$page_callback_result
[
'#ajax_commands'
];
elseif
(
is_array
(
$page_callback_result
)
&&
isset
(
$page_callback_result
[
'#type'
])
&&
(
$page_callback_result
[
'#type'
]
==
'ajax'
))
{
// Complex AJAX callbacks can return a result that contains an error message
// or a specific set of commands to send to the browser.
$page_callback_result
+=
element_info
(
'ajax'
);
$header
=
$page_callback_result
[
'#header'
];
$error
=
$page_callback_result
[
'#error'
];
if
(
isset
(
$error
)
&&
$error
!==
FALSE
)
{
if
((
empty
(
$error
)
||
$error
===
TRUE
))
{
$error
=
t
(
'An error occurred while handling the request: The server received invalid input.'
);
}
$commands
[]
=
ajax_command_alert
(
$error
);
}
else
{
$commands
=
$page_callback_result
[
'#commands'
];
}
}
else
{
...
...
@@ -405,7 +382,49 @@ function ajax_deliver($page_callback_result) {
$commands
[]
=
ajax_command_replace
(
NULL
,
$html
);
$commands
[]
=
ajax_command_prepend
(
NULL
,
theme
(
'status_messages'
));
}
ajax_render
(
$commands
);
// This function needs to do the same thing that drupal_deliver_html_page()
// does: add any needed http headers, print rendered output, and perform
// end-of-request tasks. By default, $header=TRUE, and we add a
// 'text/javascript' header. The page callback can override $header by
// returning an 'ajax' element with a #header property. This can be set to
// FALSE to prevent the 'text/javascript' header from being output, necessary
// when outputting to an IFRAME. This can also be set to 'multipart', in which
// case, we don't output JSON, but JSON content wrapped in a textarea, making
// a 'text/javascript' header incorrect.
if
(
$header
&&
$header
!==
'multipart'
)
{
drupal_add_http_header
(
'Content-Type'
,
'text/javascript; charset=utf-8'
);
}
$output
=
ajax_render
(
$commands
);
if
(
$header
===
'multipart'
)
{
// jQuery file uploads: http://malsup.com/jquery/form/#code-samples
$output
=
'<textarea>'
.
$output
.
'</textarea>'
;
}
print
$output
;
ajax_footer
();
}
/**
* Perform end-of-AJAX-request tasks.
*
* This function is the equivalent of drupal_page_footer(), but for AJAX
* requests.
*
* @see drupal_page_footer()
*/
function
ajax_footer
()
{
// Even for AJAX requests, invoke hook_exit() implementations. There may be
// modules that need very fast AJAX responses, and therefore, run AJAX
// requests with an early bootstrap.
if
(
drupal_get_bootstrap_phase
()
==
DRUPAL_BOOTSTRAP_FULL
&&
(
!
defined
(
'MAINTENANCE_MODE'
)
||
MAINTENANCE_MODE
!=
'update'
))
{
module_invoke_all
(
'exit'
);
}
// Commit the user session. See above comment about the possibility of this
// function running without session.inc loaded.
if
(
function_exists
(
'drupal_session_commit'
))
{
drupal_session_commit
();
}
}
/**
...
...
modules/book/book.pages.inc
View file @
5e32593f
...
...
@@ -237,7 +237,6 @@ function book_form_update() {
// Load the form based upon the $_POST data sent via the ajax call.
list
(
$form
,
$form_state
)
=
ajax_get_form
();
$commands
=
array
();
$bid
=
$_POST
[
'book'
][
'bid'
];
// Validate the bid.
...
...
@@ -248,15 +247,9 @@ function book_form_update() {
$form
[
'book'
][
'plid'
]
=
_book_parent_select
(
$book_link
);
form_set_cache
(
$form
[
'values'
][
'form_build_id'
],
$form
,
$form_state
);
// Build
and render the new select element, then return it in JSON forma
t.
// Build
the new select element and return i
t.
$form_state
=
array
();
$form
=
form_builder
(
$form
[
'form_id'
][
'#value'
],
$form
,
$form_state
);
$commands
[]
=
ajax_command_replace
(
NULL
,
drupal_render
(
$form
[
'book'
][
'plid'
]));
return
$form
[
'book'
][
'plid'
];
}
// @todo: We could and should just return $form['book']['plid'] and skip the
// ajax_command_replace() above. But for now, this provides a test case of
// returning an AJAX commands array.
return
array
(
'#type'
=>
'ajax_commands'
,
'#ajax_commands'
=>
$commands
);
}
modules/field/field.form.inc
View file @
5e32593f
...
...
@@ -397,7 +397,7 @@ function field_add_more_js($form, $form_state) {
$field
=
$field_info
[
'field'
];
if
(
$field
[
'cardinality'
]
!=
FIELD_CARDINALITY_UNLIMITED
)
{
ajax_render
(
array
())
;
return
;
}
// Navigate to the right element in the the form.
...
...
modules/file/file.module
View file @
5e32593f
...
...
@@ -214,7 +214,7 @@ function file_ajax_upload() {
drupal_set_message
(
t
(
'An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.'
,
array
(
'@size'
=>
format_size
(
file_upload_max_size
()))),
'error'
);
$commands
=
array
();
$commands
[]
=
ajax_command_replace
(
NULL
,
theme
(
'status_messages'
));
ajax_render
(
$commands
,
FALSE
);
return
array
(
'#type'
=>
'ajax'
,
'#commands'
=>
$commands
,
'#header'
=>
FALSE
);
}
list
(
$form
,
$form_state
,
$form_id
,
$form_build_id
)
=
ajax_get_form
();
...
...
@@ -224,7 +224,7 @@ function file_ajax_upload() {
drupal_set_message
(
t
(
'An unrecoverable error occurred. Use of this form has expired. Try reloading the page and submitting again.'
),
'error'
);
$commands
=
array
();
$commands
[]
=
ajax_command_replace
(
NULL
,
theme
(
'status_messages'
));
ajax_render
(
$commands
,
FALSE
);
return
array
(
'#type'
=>
'ajax'
,
'#commands'
=>
$commands
,
'#header'
=>
FALSE
);
}
// Get the current element and count the number of files.
...
...
@@ -261,7 +261,7 @@ function file_ajax_upload() {
$commands
=
array
();
$commands
[]
=
ajax_command_replace
(
NULL
,
$output
,
$settings
);
ajax_render
(
$commands
,
FALSE
);
return
array
(
'#type'
=>
'ajax'
,
'#commands'
=>
$commands
,
'#header'
=>
FALSE
);
}
/**
...
...
modules/simpletest/tests/ajax_forms_test.module
View file @
5e32593f
...
...
@@ -67,7 +67,7 @@ function ajax_forms_test_simple_form_select_callback($form, $form_state) {
$commands
=
array
();
$commands
[]
=
ajax_command_html
(
'#ajax_selected_color'
,
$form_state
[
'values'
][
'select'
]);
$commands
[]
=
ajax_command_data
(
'#ajax_selected_color'
,
'form_state_value_select'
,
$form_state
[
'values'
][
'select'
]);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -77,7 +77,7 @@ function ajax_forms_test_simple_form_checkbox_callback($form, $form_state) {
$commands
=
array
();
$commands
[]
=
ajax_command_html
(
'#ajax_checkbox_value'
,
(
int
)
$form_state
[
'values'
][
'checkbox'
]);
$commands
[]
=
ajax_command_data
(
'#ajax_checkbox_value'
,
'form_state_value_select'
,
(
int
)
$form_state
[
'values'
][
'checkbox'
]);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
...
...
@@ -233,7 +233,7 @@ function ajax_forms_test_advanced_commands_after_callback($form, $form_state) {
$commands
=
array
();
$commands
[]
=
ajax_command_after
(
$selector
,
"This will be placed after"
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -242,7 +242,7 @@ function ajax_forms_test_advanced_commands_after_callback($form, $form_state) {
function
ajax_forms_test_advanced_commands_alert_callback
(
$form
,
$form_state
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_alert
(
"Alert"
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -252,7 +252,7 @@ function ajax_forms_test_advanced_commands_append_callback($form, $form_state) {
$selector
=
'#append_div'
;
$commands
=
array
();
$commands
[]
=
ajax_command_append
(
$selector
,
"Appended text"
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -263,7 +263,7 @@ function ajax_forms_test_advanced_commands_before_callback($form, $form_state) {
$commands
=
array
();
$commands
[]
=
ajax_command_before
(
$selector
,
"Before text"
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -271,7 +271,7 @@ function ajax_forms_test_advanced_commands_before_callback($form, $form_state) {
*/
function
ajax_forms_test_advanced_commands_changed_callback
(
$form
,
$form_state
)
{
$commands
[]
=
ajax_command_changed
(
'#changed_div'
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
* AJAX callback for 'changed' with asterisk marking inner div.
...
...
@@ -279,7 +279,7 @@ function ajax_forms_test_advanced_commands_changed_callback($form, $form_state)
function
ajax_forms_test_advanced_commands_changed_asterisk_callback
(
$form
,
$form_state
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_changed
(
'#changed_div'
,
'#changed_div_mark_this'
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -291,7 +291,7 @@ function ajax_forms_test_advanced_commands_css_callback($form, $form_state) {
$commands
=
array
();
$commands
[]
=
ajax_command_css
(
$selector
,
array
(
'background-color'
=>
$color
));
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -302,7 +302,7 @@ function ajax_forms_test_advanced_commands_data_callback($form, $form_state) {
$commands
=
array
();
$commands
[]
=
ajax_command_data
(
$selector
,
'testkey'
,
'testvalue'
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -311,7 +311,7 @@ function ajax_forms_test_advanced_commands_data_callback($form, $form_state) {
function
ajax_forms_test_advanced_commands_html_callback
(
$form
,
$form_state
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_html
(
'#html_div'
,
'replacement text'
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -320,7 +320,7 @@ function ajax_forms_test_advanced_commands_html_callback($form, $form_state) {
function
ajax_forms_test_advanced_commands_prepend_callback
(
$form
,
$form_state
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_prepend
(
'#prepend_div'
,
"prepended text"
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -329,7 +329,7 @@ function ajax_forms_test_advanced_commands_prepend_callback($form, $form_state)
function
ajax_forms_test_advanced_commands_remove_callback
(
$form
,
$form_state
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_remove
(
'#remove_text'
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
/**
...
...
@@ -338,5 +338,5 @@ function ajax_forms_test_advanced_commands_remove_callback($form, $form_state) {
function
ajax_forms_test_advanced_commands_restripe_callback
(
$form
,
$form_state
)
{
$commands
=
array
();
$commands
[]
=
ajax_command_restripe
(
'#restripe_table'
);
return
array
(
'#type'
=>
'ajax
_commands'
,
'#ajax_
commands'
=>
$commands
);
return
array
(
'#type'
=>
'ajax
'
,
'#
commands'
=>
$commands
);
}
modules/simpletest/tests/ajax_test.module
View file @
5e32593f
...
...
@@ -13,12 +13,14 @@ function ajax_test_menu() {
$items
[
'ajax-test/render'
]
=
array
(
'title'
=>
'ajax_render'
,
'page callback'
=>
'ajax_test_render'
,
'delivery callback'
=>
'ajax_deliver'
,
'access callback'
=>
TRUE
,
'type'
=>
MENU_CALLBACK
,
);
$items
[
'ajax-test/render-error'
]
=
array
(
'title'
=>
'ajax_render_error'
,
'page callback'
=>
'ajax_test_render_error'
,
'page callback'
=>
'ajax_test_error'
,
'delivery callback'
=>
'ajax_deliver'
,
'access callback'
=>
TRUE
,
'type'
=>
MENU_CALLBACK
,
);
...
...
@@ -26,7 +28,7 @@ function ajax_test_menu() {
}
/**
* Menu callback;
Copies $_GET['commands'] into $commands and ajax_render()s that
.
* Menu callback;
Returns $_GET['commands'] suitable for use by ajax_deliver()
.
*
* Additionally ensures that ajax_render() incorporates JavaScript settings
* by invoking drupal_add_js() with a dummy setting.
...
...
@@ -40,20 +42,16 @@ function ajax_test_render() {
// Add a dummy JS setting.
drupal_add_js
(
array
(
'ajax'
=>
'test'
),
'setting'
);
// Output AJAX commands and end the request.
ajax_render
(
$commands
);
return
array
(
'#type'
=>
'ajax'
,
'#commands'
=>
$commands
);
}
/**
* Menu callback; Invokes ajax_render_error().
*
* Optionally passes $_GET['message'] to ajax_render_error().
* Menu callback; Returns AJAX element with #error property set.
*/
function
ajax_test_
render_
error
()
{
function
ajax_test_error
()
{
$message
=
''
;
if
(
!
empty
(
$_GET
[
'message'
]))
{
$message
=
$_GET
[
'message'
];
}
ajax_render_error
(
$message
);
return
array
(
'#type'
=>
'ajax'
,
'#error'
=>
$message
);
}
modules/system/system.module
View file @
5e32593f
...
...
@@ -290,8 +290,10 @@ function system_element_info() {
// HTML page, so we don't provide defaults for #theme or #theme_wrappers.
// However, modules can set these properties (for example, to provide an HTML
// debugging page that displays rather than executes AJAX commands).
$types
[
'ajax_commands'
]
=
array
(
'#ajax_commands'
=>
array
(),
$types
[
'ajax'
]
=
array
(
'#header'
=>
TRUE
,
'#commands'
=>
array
(),
'#error'
=>
NULL
,
);
$types
[
'html_tag'
]
=
array
(
'#theme'
=>
'html_tag'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment