diff --git a/classes/display/HTMLDisplayHandler.php b/classes/display/HTMLDisplayHandler.php
index 0246c3a87..c0cc31069 100644
--- a/classes/display/HTMLDisplayHandler.php
+++ b/classes/display/HTMLDisplayHandler.php
@@ -757,13 +757,20 @@ class HTMLDisplayHandler
'plugins/cookie/js.cookie.min.js',
'plugins/blankshield/blankshield.min.js',
'plugins/uri/URI.min.js',
- 'x.js',
- 'common.js',
- 'js_app.js',
- 'xml_handler.js',
- 'xml_js_filter.js',
);
+ if (str_contains($_SERVER['HTTP_USER_AGENT'] ?? '', 'Trident/'))
+ {
+ $original_file_list[] = 'polyfills/formdata.min.js';
+ $original_file_list[] = 'polyfills/promise.min.js';
+ }
+
+ $original_file_list[] = 'x.js';
+ $original_file_list[] = 'common.js';
+ $original_file_list[] = 'js_app.js';
+ $original_file_list[] = 'xml_handler.js';
+ $original_file_list[] = 'xml_js_filter.js';
+
if(config('view.minify_scripts') === 'none')
{
Context::loadFile(array('./common/js/jquery-' . $jquery_version . '.js', 'head', '', -1800000000), true);
diff --git a/classes/frontendfile/FrontEndFileHandler.class.php b/classes/frontendfile/FrontEndFileHandler.class.php
index a530ee3ce..034d190aa 100644
--- a/classes/frontendfile/FrontEndFileHandler.class.php
+++ b/classes/frontendfile/FrontEndFileHandler.class.php
@@ -430,6 +430,10 @@ class FrontEndFileHandler extends Handler
public function unloadFile($fileName, $unused = '', $media = 'all')
{
$file = $this->getFileInfo($fileName, $unused, $media);
+ if (!isset($file->key))
+ {
+ return;
+ }
if($file->fileExtension == 'css')
{
diff --git a/classes/module/ModuleObject.class.php b/classes/module/ModuleObject.class.php
index a736136f4..0d5b4d3d8 100644
--- a/classes/module/ModuleObject.class.php
+++ b/classes/module/ModuleObject.class.php
@@ -254,15 +254,15 @@ class ModuleObject extends BaseObject
// Get privileges(granted) information for target module by of module.xml
if(($permission = $this->xml_info->action->{$this->act}->permission) && $permission->check_var)
{
- // Check parameter
- if(empty($check_module_srl = trim(Context::get($permission->check_var))))
+ // Ensure that the list of modules to check is the right type and not empty
+ $check_var = Context::get($permission->check_var);
+ if (is_scalar($check_var))
{
- return false;
- }
+ if (empty($check_module_srl = trim($check_var)))
+ {
+ return false;
+ }
- // If value is not array
- if(!is_array($check_module_srl))
- {
// Convert string to array. delimiter is ,(comma) or |@|
if(preg_match('/,|\|@\|/', $check_module_srl, $delimiter) && $delimiter[0])
{
@@ -273,6 +273,14 @@ class ModuleObject extends BaseObject
$check_module_srl = array($check_module_srl);
}
}
+ else
+ {
+ $check_module_srl = array_map('trim', $check_var);
+ if (!count($check_var))
+ {
+ return false;
+ }
+ }
// Check permission by privileges(granted) information for target module
foreach($check_module_srl as $target_srl)
@@ -295,7 +303,15 @@ class ModuleObject extends BaseObject
}
// Check permission based on the grant information for the current module.
- $grant = ModuleModel::getInstance()->getGrant($this->module_info, $this->user, $this->xml_info);
+ if (isset($check_grant))
+ {
+ $grant = $check_grant;
+ }
+ else
+ {
+ $grant = ModuleModel::getInstance()->getGrant($this->module_info, $this->user, $this->xml_info);
+ }
+
if(!$this->checkPermission($grant, $this->user, $failed_requirement))
{
$this->stop($this->_generatePermissionError($failed_requirement));
diff --git a/common/constants.php b/common/constants.php
index 3589e734d..fde0b485f 100644
--- a/common/constants.php
+++ b/common/constants.php
@@ -3,7 +3,7 @@
/**
* RX_VERSION is the version number of the Rhymix CMS.
*/
-define('RX_VERSION', '2.1.23');
+define('RX_VERSION', '2.1.25');
/**
* RX_MICROTIME is the startup time of the current script, in microseconds since the Unix epoch.
diff --git a/common/framework/parsers/template/TemplateParser_v2.php b/common/framework/parsers/template/TemplateParser_v2.php
index 501845a2a..399e45d97 100644
--- a/common/framework/parsers/template/TemplateParser_v2.php
+++ b/common/framework/parsers/template/TemplateParser_v2.php
@@ -185,7 +185,7 @@ class TemplateParser_v2
}, $content);
// Inline scripts.
- $content = preg_replace_callback('#(?<=\s)(href="javascript:|on[a-z]+=")([^"]*?)"#i', function($match) {
+ $content = preg_replace_callback('#(?<=\s)(href="javascript:|pattern="|on[a-z]+=")([^"]*?)"#i', function($match) {
return $match[1] . 'config->context = \'JS\'; ?>' . $match[2] . 'config->context = \'HTML\'; ?>"';
}, $content);
diff --git a/common/js/common.js b/common/js/common.js
index 9033e49e2..728085456 100644
--- a/common/js/common.js
+++ b/common/js/common.js
@@ -262,14 +262,37 @@ Rhymix.isSameHost = function(url) {
* Redirect to a URL, but reload instead if the target is the same as the current page
*
* @param string url
+ * @param int delay
* @return void
*/
-Rhymix.redirectToUrl = function(url) {
- if (this.isCurrentUrl(url)) {
- window.location.href = url;
- window.location.reload();
+Rhymix.redirectToUrl = function(url, delay) {
+ const callback = function() {
+ if (Rhymix.isCurrentUrl(url)) {
+ window.location.href = url;
+ window.location.reload();
+ } else {
+ window.location.href = url;
+ }
+ };
+ if (delay) {
+ this.pendingRedirect = setTimeout(callback, delay);
} else {
- window.location.href = url;
+ callback();
+ }
+};
+
+/**
+ * Cancel any pending redirect
+ *
+ * @return bool
+ */
+Rhymix.cancelPendingRedirect = function() {
+ if (this.pendingRedirect) {
+ clearTimeout(this.pendingRedirect);
+ this.pendingRedirect = null;
+ return true;
+ } else {
+ return false;
}
};
@@ -398,16 +421,26 @@ Rhymix.modal.close = function(id) {
*
* @param string action
* @param object params
- * @param function success
- * @param function error
- * @return void
+ * @param function callback_success
+ * @param function callback_error
+ * @return Promise
*/
-Rhymix.ajax = function(action, params, success, error) {
+Rhymix.ajax = function(action, params, callback_success, callback_error) {
// Extract module and act
let isFormData = params instanceof FormData;
- let module, act;
- if (!action) {
+ let module, act, url, promise;
+ if (action) {
+ if (typeof action === 'string' && action.match(/^[a-z0-9_]+\.[a-z0-9_]+$/i)) {
+ let parts = action.split('.');
+ params = params || {};
+ params.module = module = parts[0];
+ params.act = act = parts[1];
+ } else {
+ url = action;
+ action = null;
+ }
+ } else {
if (isFormData) {
module = params.get('module');
act = params.get('act');
@@ -421,26 +454,22 @@ Rhymix.ajax = function(action, params, success, error) {
} else {
action = null;
}
- } else {
- action = action.split('.');
- params = params || {};
- params.module = module = action[0];
- params.act = act = action[1];
- action = action.join('.');
}
// Add action to URL if the current rewrite level supports it
- let url = this.URI(window.request_uri).pathname() + 'index.php';
- if (act) {
- url = url + '?act=' + act;
+ if (!url) {
+ url = this.URI(window.request_uri).pathname() + 'index.php';
+ if (act) {
+ url = url + '?act=' + act;
+ }
+ /*
+ if (this.getRewriteLevel() >= 2 && action !== null) {
+ url = url + '_' + action.replace('.', '/');
+ } else {
+ url = url + 'index.php';
+ }
+ */
}
- /*
- if (this.getRewriteLevel() >= 2 && action !== null) {
- url = url + action.replace('.', '/');
- } else {
- url = url + 'index.php';
- }
- */
// Add a CSRF token to the header, and remove it from the parameters
const headers = {
@@ -453,175 +482,137 @@ Rhymix.ajax = function(action, params, success, error) {
delete params._rx_csrf_token;
}
- // Generate AJAX parameters
- const args = {
- type: 'POST',
- dataType: 'json',
- url: url,
- data: isFormData ? params : JSON.stringify(params),
- contentType: isFormData ? false : 'application/json; charset=UTF-8',
- processData: false,
- headers: headers,
- success: function(data, textStatus, xhr) {
- Rhymix._ajaxSuccessHandler(xhr, textStatus, action, data, params, success, error);
- },
- error: function(xhr, textStatus, errorThrown) {
- Rhymix._ajaxErrorHandler(xhr, textStatus, action, url, params, success, error);
- }
- };
+ // Create and return a Promise for this AJAX request
+ return promise = new Promise(function(resolve, reject) {
- // Send the AJAX request
- try {
- $.ajax(args);
- } catch(e) {
- alert(e);
- }
-};
+ // Define the success wrapper.
+ const successWrapper = function(data, textStatus, xhr) {
-/**
- * Default success handler for AJAX requests
- *
- * @param object xhr
- * @param string textStatus
- * @param string action
- * @param object data
- * @param object params
- * @param function success
- * @param function errror
- * @return void
- */
-Rhymix._ajaxSuccessHandler = function(xhr, textStatus, action, data, params, success, error) {
-
- // Add debug information.
- if (data._rx_debug) {
- data._rx_debug.page_title = "AJAX : " + action;
- if (this.addDebugData) {
- this.addDebugData(data._rx_debug);
- } else {
- this.pendingDebugData.push(data._rx_debug);
- }
- }
-
- // If the response contains a Rhymix error code, display the error message.
- if (typeof data.error !== 'undefined' && data.error != 0) {
-
- // If an error callback is defined, call it. Abort if it returns false.
- if ($.isFunction(error) && error(data, xhr) === false) {
- return;
- }
-
- // If an error message was supplied, display it.
- if (data.message) {
- let msg = data.message.replace(/\\n/g, "\n");
- if (data.errorDetail) {
- msg += "\n\n" + data.errorDetail;
+ // Add debug information.
+ if (data._rx_debug) {
+ data._rx_debug.page_title = "AJAX : " + action;
+ if (Rhymix.addDebugData) {
+ Rhymix.addDebugData(data._rx_debug);
+ } else {
+ Rhymix.pendingDebugData.push(data._rx_debug);
+ }
}
- alert(msg);
- return;
- }
- // Rhymix should never return an error code without a message, but if someone does, we handle it here.
- let msg = 'AJAX error: ' + (action || 'form submission') + "\n\n" + xhr.responseText;
- if (msg.length > 1000) {
- msg = msg.substring(0, 1000) + '...';
- }
- console.error(msg.trim().replace(/\n+/g, "\n"));
- if (this.showAjaxErrors.indexOf('ALL') >= 0 || this.showAjaxErrors.indexOf(xhr.status) >= 0) {
- alert(msg.trim());
- }
- return;
- }
+ // If the response contains a Rhymix error code, display the error message.
+ if (typeof data.error !== 'undefined' && data.error != 0) {
+ return errorWrapper(data, textStatus, xhr);
+ }
- // If a success callback was defined, call it.
- if ($.isFunction(success)) {
- success(data, xhr);
- return;
- }
+ // If a success callback was defined, call it.
+ if (typeof callback_success === 'function') {
+ callback_success(data, xhr);
+ resolve(data);
+ return;
+ }
- // If the response contains a redirect URL, follow the redirect.
- if (data.redirect_url) {
- this.redirectToUrl(data.redirect_url.replace(/&/g, '&'));
- return;
- }
-};
+ // If the response contains a redirect URL, follow the redirect.
+ // This can be canceled by Rhymix.cancelPendingRedirect() within 100 milliseconds.
+ if (data.redirect_url) {
+ Rhymix.redirectToUrl(data.redirect_url.replace(/&/g, '&'), 100);
+ }
-/**
- * Default error handler for AJAX requests
- *
- * @param object xhr
- * @param string textStatus
- * @param string action
- * @param string url
- * @param object params
- * @param function success
- * @param function errror
- * @return void
- */
-Rhymix._ajaxErrorHandler = function(xhr, textStatus, action, url, params, success, error) {
+ // Resolve the promise with the response data.
+ resolve(data);
+ };
- // If the user is navigating away, don't do anything.
- if (xhr.status == 0 && this.unloading) {
- return;
- }
+ // Define the error wrapper.
+ const errorWrapper = function(data, textStatus, xhr) {
- // If the response contains valid JSON, call the success callback instead.
- if (xhr.status >= 400 && xhr.responseText) {
- let data;
- try {
- data = JSON.parse(xhr.responseText);
- } catch (e) { }
- if (data && typeof data.error !== 'undefined') {
- this._ajaxSuccessHandler(xhr, textStatus, action, data, params, success, error);
- return;
- }
- }
+ // If an error callback is defined, call it.
+ // The promise will still be rejected, but silently.
+ if (typeof callback_error === 'function') {
+ callback_error(data, xhr);
+ promise.catch(function(dummy) { });
+ let dummy = new Error('Rhymix.ajax() error already handled by callback function');
+ dummy._rx_ajax_error = true;
+ dummy.cause = data;
+ dummy.details = '';
+ dummy.xhr = xhr;
+ reject(dummy);
+ return;
+ }
- // If an error callback is defined, call it. Abort if it returns false.
- if ($.isFunction(error)) {
- let fakedata = { error: -3, message: textStatus };
- if (error(fakedata, xhr) === false) {
- return;
- }
- }
+ // Otherwise, generate a generic error message.
+ let error_message = 'AJAX error: ' + (action || 'form submission');
+ let error_details = '';
+ if (data.error != 0 && data.message) {
+ error_message = data.message.replace(/\\n/g, "\n");
+ if (data.errorDetail) {
+ error_details = data.errorDetail;
+ }
+ } else if (xhr.status == 0) {
+ error_details = 'Connection failed: ' + url + "\n\n" + (xhr.responseText || '');
+ } else {
+ error_details = (xhr.responseText || '');
+ }
+ if (error_details.length > 1000) {
+ error_details = error_details.substring(0, 1000) + '...';
+ }
- // Otherwise, generate a simple error message.
- let error_info, msg;
- if (xhr.status == 0) {
- error_info = 'Connection failed: ' + url + "\n\n" + (xhr.responseText || '');
- } else {
- error_info = 'Response code: ' + xhr.status + "\n\n" + (xhr.responseText || '');
- }
- msg = 'AJAX error: ' + (action || 'form submission') + "\n\n" + error_info;
- if (msg.length > 1000) {
- msg = msg.substring(0, 1000) + '...';
- }
+ // Reject the promise with an error object.
+ // If uncaught, this will be handled by the 'unhandledrejection' event listener.
+ const err = new Error(error_message);
+ err._rx_ajax_error = true;
+ err.cause = data;
+ err.details = error_details;
+ err.xhr = xhr;
+ reject(err);
+ };
- // Print the error message.
- console.error(msg.trim().replace(/\n+/g, "\n"));
- if (this.showAjaxErrors.indexOf('ALL') >= 0 || this.showAjaxErrors.indexOf(xhr.status) >= 0) {
- alert(msg.trim());
- }
+ // Pass off to jQuery with another wrapper around the success and error wrappers.
+ // This allows us to handle HTTP 400+ error codes with valid JSON responses.
+ $.ajax({
+ type: 'POST',
+ dataType: 'json',
+ url: url,
+ data: isFormData ? params : JSON.stringify(params),
+ contentType: isFormData ? false : 'application/json; charset=UTF-8',
+ processData: false,
+ headers: headers,
+ success: successWrapper,
+ error: function(xhr, textStatus, errorThrown) {
+ if (xhr.status == 0 && Rhymix.unloading) {
+ return;
+ }
+ if (xhr.status >= 400 && xhr.responseText) {
+ try {
+ let data = JSON.parse(xhr.responseText);
+ if (data) {
+ successWrapper(data, textStatus, xhr);
+ return;
+ }
+ } catch (e) { }
+ }
+ errorWrapper({ error: 0, message: textStatus }, textStatus, xhr);
+ }
+ });
+ });
};
/**
* Submit a form using AJAX instead of navigating away
*
* @param HTMLElement form
- * @param function success
- * @param function error
+ * @param function callback_success
+ * @param function callback_error
* @return void
*/
-Rhymix.ajaxForm = function(form, success, error) {
+Rhymix.ajaxForm = function(form, callback_success, callback_error) {
const $form = $(form);
// Get success and error callback functions.
- if (typeof success === 'undefined') {
- success = $form.data('callbackSuccess');
- if (success && $.isFunction(success)) {
+ if (typeof callback_success === 'undefined') {
+ callback_success = $form.data('callbackSuccess');
+ if (callback_success && typeof callback_success === 'function') {
// no-op
- } else if (success && window[success] && $.isFunction(window[success])) {
- success = window[success];
+ } else if (callback_success && window[callback_success] && typeof window[callback_success] === 'function') {
+ callback_success = window[callback_success];
} else {
- success = function(data) {
+ callback_success = function(data) {
if (data.message && data.message !== 'success') {
alert(data.message);
}
@@ -631,17 +622,17 @@ Rhymix.ajaxForm = function(form, success, error) {
};
}
}
- if (typeof error === 'undefined') {
- error = $form.data('callbackError');
- if (error && $.isFunction(error)) {
+ if (typeof callback_error === 'undefined') {
+ callback_error = $form.data('callbackError');
+ if (callback_error && typeof callback_error === 'function') {
// no-op
- } else if (error && window[error] && $.isFunction(window[error])) {
- error = window[error];
+ } else if (callback_error && window[callback_error] && typeof window[callback_error] === 'function') {
+ callback_error = window[callback_error];
} else {
- error = null;
+ callback_error = null;
}
}
- this.ajax(null, new FormData($form[0]), success, error);
+ this.ajax(null, new FormData($form[0]), callback_success, callback_error);
};
/**
@@ -653,7 +644,7 @@ Rhymix.ajaxForm = function(form, success, error) {
* @return void
*/
Rhymix.checkboxToggleAll = function(name) {
- if (!window[name]) {
+ if (typeof name === 'undefined') {
name='cart';
}
let options = {
@@ -1012,7 +1003,7 @@ $(function() {
e.preventDefault();
e.stopPropagation();
- if (window[Rhymix.loadedPopupMenus[params.menu_id]]) {
+ if (Rhymix.loadedPopupMenus[params.menu_id]) {
return Rhymix.displayPopupMenu(params, response_tags, params);
}
@@ -1101,6 +1092,20 @@ window.addEventListener('beforeunload', function() {
Rhymix.unloading = true;
});
+// General handler for unhandled Promise rejections
+window.addEventListener('unhandledrejection', function(event) {
+ if (event.reason && typeof event.reason['_rx_ajax_error'] === 'boolean') {
+ event.preventDefault();
+ const error_message = event.reason.message.trim();
+ const error_details = event.reason.details || '';
+ const error_xhr = event.reason.xhr || {};
+ console.error(error_message.replace(/\n+/g, "\n" + error_details));
+ if (Rhymix.showAjaxErrors.indexOf('ALL') >= 0 || Rhymix.showAjaxErrors.indexOf(error_xhr.status) >= 0) {
+ alert(error_message.trim() + (error_details ? ("\n\n" + error_details) : ''));
+ }
+ }
+});
+
// General handler for popstate events
window.addEventListener('popstate', function(event) {
// Close modal if it is open
@@ -1122,6 +1127,15 @@ window.addEventListener('popstate', function(event) {
}
});
+// Fix for browsers that don't support the unhandledrejection event
+if (typeof Promise._unhandledRejectionFn !== 'undefined') {
+ Promise._unhandledRejectionFn = function(error) {
+ if (error['_rx_ajax_error']) {
+ alert(error.message.trim());
+ }
+ };
+}
+
/**
* =================
* jQuery extensions
@@ -1457,12 +1471,16 @@ function popopen(url, target) {
* @return void
*/
function doAddDocumentCart(obj) {
- Rhymix.addedDocument.push(obj.value);
+ if (obj && obj.value) {
+ Rhymix.addedDocument.push(obj.value);
+ }
setTimeout(function() {
- exec_json('document.procDocumentAddCart', {
- srls: Rhymix.addedDocument.join(',')
- });
- Rhymix.addedDocument = [];
+ if (Rhymix.addedDocument.length > 0) {
+ exec_json('document.procDocumentAddCart', {
+ srls: Rhymix.addedDocument
+ });
+ Rhymix.addedDocument = [];
+ }
}, 100);
}
diff --git a/common/js/polyfills/formdata.min.js b/common/js/polyfills/formdata.min.js
new file mode 100644
index 000000000..f4abd6765
--- /dev/null
+++ b/common/js/polyfills/formdata.min.js
@@ -0,0 +1,21 @@
+/*! formdata-polyfill. MIT License. Jimmy W?rting */
+;(function(){var h;function l(a){var b=0;return function(){return b>>0)+"_",e=0;return b});
+r("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;cf;f++)r(f,o[f])})}function n(e,t){this.name="AggregateError",this.errors=e,this.message=t||""}function r(e){var t=this;return new t(function(r,o){if(!e||"undefined"==typeof e.length)return o(new TypeError("Promise.any accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return o();for(var f=[],u=0;i.length>u;u++)try{t.resolve(i[u]).then(r)["catch"](function(e){f.push(e),f.length===i.length&&o(new n(f,"All promises were rejected"))})}catch(c){o(c)}})}function o(e){return!(!e||"undefined"==typeof e.length)}function i(){}function f(e){if(!(this instanceof f))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],s(e,this)}function u(e,t){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,f._immediateFn(function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null!==n){var r;try{r=n(e._value)}catch(o){return void a(t.promise,o)}c(t.promise,r)}else(1===e._state?c:a)(t.promise,e._value)})):e._deferreds.push(t)}function c(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var n=t.then;if(t instanceof f)return e._state=3,e._value=t,void l(e);if("function"==typeof n)return void s(function(e,t){return function(){e.apply(t,arguments)}}(n,t),e)}e._state=1,e._value=t,l(e)}catch(r){a(e,r)}}function a(e,t){e._state=2,e._value=t,l(e)}function l(e){2===e._state&&0===e._deferreds.length&&f._immediateFn(function(){e._handled||f._unhandledRejectionFn(e._value)});for(var t=0,n=e._deferreds.length;n>t;t++)u(e,e._deferreds[t]);e._deferreds=null}function s(e,t){var n=!1;try{e(function(e){n||(n=!0,c(t,e))},function(e){n||(n=!0,a(t,e))})}catch(r){if(n)return;n=!0,a(t,r)}}n.prototype=Error.prototype;var d=setTimeout;f.prototype["catch"]=function(e){return this.then(null,e)},f.prototype.then=function(e,t){var n=new this.constructor(i);return u(this,new function(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}(e,t,n)),n},f.prototype["finally"]=e,f.all=function(e){return new f(function(t,n){function r(e,o){try{if(o&&("object"==typeof o||"function"==typeof o)){var u=o.then;if("function"==typeof u)return void u.call(o,function(t){r(e,t)},n)}i[e]=o,0==--f&&t(i)}catch(c){n(c)}}if(!o(e))return n(new TypeError("Promise.all accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var f=i.length,u=0;i.length>u;u++)r(u,i[u])})},f.any=r,f.allSettled=t,f.resolve=function(e){return e&&"object"==typeof e&&e.constructor===f?e:new f(function(t){t(e)})},f.reject=function(e){return new f(function(t,n){n(e)})},f.race=function(e){return new f(function(t,n){if(!o(e))return n(new TypeError("Promise.race accepts an array"));for(var r=0,i=e.length;i>r;r++)f.resolve(e[r]).then(t,n)})},f._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){d(e,0)},f._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var p=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"function"!=typeof p.Promise?p.Promise=f:(p.Promise.prototype["finally"]||(p.Promise.prototype["finally"]=e),p.Promise.allSettled||(p.Promise.allSettled=t),p.Promise.any||(p.Promise.any=r))});
diff --git a/common/js/xml_js_filter.js b/common/js/xml_js_filter.js
index 83459d213..414c175d8 100644
--- a/common/js/xml_js_filter.js
+++ b/common/js/xml_js_filter.js
@@ -467,13 +467,13 @@ function legacy_filter(filter_name, form, module, act, callback, responses, conf
};
if (!hasFile) {
- Rhymix.ajax(module + '.' + act, params, callback_wrapper);
+ exec_json(module + '.' + act, params, callback_wrapper);
} else {
var fd = new FormData();
for (let key in params) {
fd.append(key, params[key]);
}
- Rhymix.ajax(null, fd, callback_wrapper);
+ exec_json('raw', fd, callback_wrapper);
}
};
diff --git a/common/tpl/popup_layout.html b/common/tpl/popup_layout.html
index 556864c29..5252377f9 100644
--- a/common/tpl/popup_layout.html
+++ b/common/tpl/popup_layout.html
@@ -11,7 +11,9 @@
const iframe_sequence = '{{ $iframe_sequence }}';
window.opener = window.parent;
window.close = function() {
- parent.closeModal('_rx_iframe_' + iframe_sequence);
+ setTimeout(function() {
+ parent.closeModal('_rx_iframe_' + iframe_sequence);
+ }, 100);
};
';
$target = '';
diff --git a/widgets/content/conf/info.xml b/widgets/content/conf/info.xml
index ca28e37de..cfef3d17e 100644
--- a/widgets/content/conf/info.xml
+++ b/widgets/content/conf/info.xml
@@ -246,7 +246,7 @@
UL (list)
-
+
목록수
目录数
リスト数
@@ -266,7 +266,7 @@
設置要顯示的目錄數。(預設是5個)
Görüntülenecek yazıların sayısını ayarlayabilirsiniz. (varsayılan değer 5'tir)
-
+
가로 이미지 수
横並びイメージ数
横向图片数