diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 7377cecf1..dc7c8f5a9 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -166,6 +166,7 @@ class Context private static $_reserved_keys = array( '_rx_ajax_compat' => true, '_rx_csrf_token' => true, + '_rx_target_iframe' => true, ); /** diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php index c32074e32..ab7f0c1c4 100644 --- a/classes/module/ModuleHandler.class.php +++ b/classes/module/ModuleHandler.class.php @@ -940,6 +940,24 @@ class ModuleHandler extends Handler $methodList = array('XMLRPC' => 1, 'JSON' => 1, 'JS_CALLBACK' => 1); if(!isset($methodList[Context::getRequestMethod()])) { + // Handle iframe form submissions. + if(isset($_POST['_rx_target_iframe']) && starts_with('_rx_temp_', $_POST['_rx_target_iframe'])) + { + if($_SESSION['XE_VALIDATOR_RETURN_URL']) + { + ob_end_clean(); + echo sprintf('
', json_encode($_SESSION['XE_VALIDATOR_RETURN_URL'])); + return; + } + if($this->error) + { + ob_end_clean(); + echo sprintf('', json_encode($this->error), json_encode($_POST['_rx_target_iframe'])); + return; + } + } + + // Handle redirects. if($_SESSION['XE_VALIDATOR_RETURN_URL']) { if ($_SESSION['is_new_session']) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index b5780e8b3..eb6d531bd 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -190,16 +190,19 @@ window.exec_json = $.exec_json = function(action, params, callback_success, callback_error) { // Convert params to object and fill in the module and act. - params = params ? ($.isArray(params) ? arr2obj(params) : params) : {}; - action = action.split("."); - //if (action.length != 2) return; - params.module = action[0]; - params.act = action[1]; - params._rx_ajax_compat = 'JSON'; - params._rx_csrf_token = getCSRFToken(); - - // Fill in the XE vid. - if (typeof(xeVid) != "undefined") params.vid = xeVid; + var request_info; + if (action === 'raw') { + request_info = 'RAW FORM SUBMISSION'; + } else { + params = params ? ($.isArray(params) ? arr2obj(params) : params) : {}; + action = action.split("."); + //if (action.length != 2) return; + params.module = action[0]; + params.act = action[1]; + params._rx_ajax_compat = 'JSON'; + params._rx_csrf_token = getCSRFToken(); + request_info = params.module + "." + params.act; + } // Delay the waiting message for 1 second to prevent rapid blinking. waiting_obj.css("opacity", 0.0); @@ -218,7 +221,7 @@ // Add debug information. if (data._rx_debug) { - data._rx_debug.page_title = "AJAX : " + params.module + "." + params.act; + data._rx_debug.page_title = "AJAX : " + request_info; if (window.rhymix_debug_add_data) { window.rhymix_debug_add_data(data._rx_debug); } else { @@ -238,7 +241,7 @@ if (data.message) { alert(data.message.replace(/\\n/g, "\n")); } else { - alert("AJAX communication error while requesting " + data.module + "." + data.act); + alert("AJAX communication error while requesting " + request_info); } if ($.isFunction(callback_error)) { callback_error(data); @@ -283,6 +286,7 @@ dataType: "json", url: request_uri, data: params, + processData: (action !== 'raw'), success : successHandler, error : errorHandler }); @@ -356,6 +360,52 @@ } }; + /** + * Function for AJAX submission of arbitrary forms. + */ + $(document).on('submit', 'form.rx_ajax', function(event) { + // Abort if the form already has a 'target' attribute. + var form = $(this); + if (form.attr('target')) { + return; + } + // Prevent page refresh. + event.preventDefault(); + // Get success and error callback functions. + var callback_success = form.data('callback-success'); + if (callback_success && window[callback_success] && $.isFunction(window[callback_success])) { + callback_success = window[callback_success]; + } else { + callback_success = null; + } + var callback_error = form.data('callback-error'); + if (callback_error && window[callback_error] && $.isFunction(window[callback_error])) { + callback_error = window[callback_error]; + } else { + callback_error = null; + } + // If the form has file uploads, use a hidden iframe to submit. Otherwise use exec_json. + var has_files = form.find('input[type=file][name!=Filedata]').size(); + if (has_files) { + var iframe_id = '_rx_temp_' + (new Date()).getTime(); + $('').appendTo($(document.body)); + form.attr('method', 'POST').attr('enctype', 'multipart/form-data'); + form.attr('target', iframe_id).find('input[name=_rx_target_iframe]').remove(); + form.append(''); + window.remove_iframe = function(iframe_id) { + if (iframe_id.match(/^_rx_temp_[0-9]+$/)) { + $('iframe#' + iframe_id).remove(); + } + }; + setTimeout(function() { + form.removeAttr('target').find('input[name=_rx_target_iframe]').remove(); + }, 1000); + form.submit(); + } else { + window.exec_json('raw', form.serialize(), callback_success, callback_error); + } + }); + /** * Empty placeholder for beforeUnload handler. */