mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-03 08:41:39 +09:00
2275 lines
53 KiB
JavaScript
2275 lines
53 KiB
JavaScript
/**
|
|
* Common JavaScript library for Rhymix, based on XpressEngine 1.x
|
|
*/
|
|
|
|
/**
|
|
* =============
|
|
* Rhymix object
|
|
* =============
|
|
*/
|
|
|
|
const Rhymix = window.Rhymix = {
|
|
addedDocument: [],
|
|
langCodes: {},
|
|
loadedPopupMenus: [],
|
|
openWindowList: {},
|
|
currentDebugData: null,
|
|
pendingDebugData: [],
|
|
showAjaxErrors: ['ALL'],
|
|
unloading: false,
|
|
modal: {},
|
|
state: {}
|
|
};
|
|
|
|
/**
|
|
* Check if the current device is a mobile device.
|
|
*
|
|
* @return bool
|
|
*/
|
|
Rhymix.isMobile = function() {
|
|
return String(navigator.userAgent).match(/mobile/i);
|
|
};
|
|
|
|
/**
|
|
* Get the current color scheme
|
|
*
|
|
* @return string
|
|
*/
|
|
Rhymix.getColorScheme = function() {
|
|
if ($('body').hasClass('color_scheme_dark')) {
|
|
return 'dark';
|
|
} else {
|
|
return 'light';
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set the color scheme
|
|
*
|
|
* @param string color_scheme
|
|
* @return void
|
|
*/
|
|
Rhymix.setColorScheme = function(color_scheme) {
|
|
if (color_scheme === 'dark' || color_scheme === 'light') {
|
|
$('body').addClass('color_scheme_' + color_scheme).removeClass('color_scheme_' + (color_scheme === 'dark' ? 'light' : 'dark'));
|
|
this.cookie.set('rx_color_scheme', color_scheme, { path: this.URI(default_url).pathname(), expires: 365 });
|
|
} else {
|
|
this.cookie.remove('rx_color_scheme', { path: this.URI(default_url).pathname() });
|
|
color_scheme = (window.matchMedia && window.matchMedia('(prefers-color-scheme:dark)').matches) ? 'dark' : 'light';
|
|
$('body').addClass('color_scheme_' + color_scheme).removeClass('color_scheme_' + (color_scheme === 'dark' ? 'light' : 'dark'));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Automatically detect the color scheme
|
|
*
|
|
* @return void
|
|
*/
|
|
Rhymix.detectColorScheme = function() {
|
|
// Return if a color scheme is already selected.
|
|
const body_element = $('body');
|
|
if(body_element.hasClass('color_scheme_light') || body_element.hasClass('color_scheme_dark')) {
|
|
return;
|
|
}
|
|
// Detect the cookie.
|
|
let color_scheme = this.cookie.get('rx_color_scheme');
|
|
// Detect the device color scheme.
|
|
let match_media = window.matchMedia ? window.matchMedia('(prefers-color-scheme:dark)') : null;
|
|
if (color_scheme !== 'light' && color_scheme !== 'dark') {
|
|
color_scheme = (match_media && match_media.matches) ? 'dark' : 'light';
|
|
}
|
|
// Set the body class according to the detected color scheme.
|
|
body_element.addClass('color_scheme_' + color_scheme);
|
|
// Add an event listener to detect changes to the device color scheme.
|
|
match_media && match_media.addListener && match_media.addListener(function(e) {
|
|
if (e.matches) {
|
|
body_element.removeClass('color_scheme_light').addClass('color_scheme_dark');
|
|
} else {
|
|
body_element.removeClass('color_scheme_dark').addClass('color_scheme_light');
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Get the language
|
|
*
|
|
* @return string
|
|
*/
|
|
Rhymix.getLangType = function() {
|
|
return window.current_lang;
|
|
};
|
|
|
|
/**
|
|
* Set the language
|
|
*
|
|
* @param string lang_type
|
|
* @return void
|
|
*/
|
|
Rhymix.setLangType = function(lang_type) {
|
|
const baseurl = this.getBaseUrl();
|
|
if (baseurl !== '/') {
|
|
this.cookie.remove('lang_type', { path: '/' });
|
|
}
|
|
this.cookie.set('lang_type', lang_type, { path: baseurl, expires: 365 });
|
|
};
|
|
|
|
/**
|
|
* Get CSRF token for this document
|
|
*
|
|
* @return string|null
|
|
*/
|
|
Rhymix.getCSRFToken = function() {
|
|
return $("meta[name='csrf-token']").attr("content");
|
|
};
|
|
|
|
/**
|
|
* Set CSRF token for this document
|
|
*
|
|
* @param string token
|
|
* @return void
|
|
*/
|
|
Rhymix.setCSRFToken = function(token) {
|
|
$("meta[name='csrf-token']").attr("content", token);
|
|
};
|
|
|
|
/**
|
|
* Get the current rewrite level
|
|
*
|
|
* @return int
|
|
*/
|
|
Rhymix.getRewriteLevel = function() {
|
|
return window.rewrite_level;
|
|
};
|
|
|
|
/**
|
|
* Get the base URL relative to the current origin
|
|
*
|
|
* @return string
|
|
*/
|
|
Rhymix.getBaseUrl = function() {
|
|
if (!this.state.baseUrl) {
|
|
this.state.baseUrl = this.URI(default_url).pathname();
|
|
}
|
|
return this.state.baseUrl;
|
|
};
|
|
|
|
/**
|
|
* Get the full default URL
|
|
*
|
|
* @return string
|
|
*/
|
|
Rhymix.getDefaultUrl = function() {
|
|
return window.default_url;
|
|
};
|
|
|
|
/**
|
|
* Get the current page's long URL
|
|
*
|
|
* @return string
|
|
*/
|
|
Rhymix.getCurrentUrl = function() {
|
|
return window.current_url;
|
|
};
|
|
|
|
/**
|
|
* Get the current page prefix (mid)
|
|
*
|
|
* @return string
|
|
*/
|
|
Rhymix.getCurrentUrlPrefix = function() {
|
|
return window.current_mid;
|
|
};
|
|
|
|
/**
|
|
* Check if a URL is identical to the current page URL except for the hash
|
|
*
|
|
* @param string url
|
|
* @return bool
|
|
*/
|
|
Rhymix.isCurrentUrl = function(url) {
|
|
const absolute_url = window.location.href;
|
|
const relative_url = window.location.pathname + window.location.search;
|
|
return url === absolute_url || url === relative_url ||
|
|
url.indexOf(absolute_url.replace(/#.+$/, "") + "#") === 0 ||
|
|
url.indexOf(relative_url.replace(/#.+$/, "") + "#") === 0;
|
|
};
|
|
|
|
/**
|
|
* Check if two URLs belong to the same origin
|
|
*
|
|
* @param string url1
|
|
* @param string url2
|
|
* @return bool
|
|
*/
|
|
Rhymix.isSameOrigin = function(url1, url2) {
|
|
if(!url1 || !url2) {
|
|
return false;
|
|
}
|
|
if (url1.match(/^\.?\/[^\/]*/) || url2.match(/^\.?\/[^\/]*/)) {
|
|
return true;
|
|
}
|
|
if (url1.match(/^(https?:)?\/\/[^\/]*[^a-z0-9\/.:_-]/i) || url2.match(/^(https?:)?\/\/[^\/]*[^a-z0-9\/.:_-]/i)) {
|
|
return false;
|
|
}
|
|
try {
|
|
url1 = this.URI(url1).normalizePort().normalizeHostname().normalizePathname().origin();
|
|
url2 = this.URI(url2).normalizePort().normalizeHostname().normalizePathname().origin();
|
|
return (url1 === url2) ? true : false;
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a URL belongs to the same host as the current page
|
|
*
|
|
* Note that this function does not check the protocol.
|
|
* It is therefore a weaker check than isSameOrigin().
|
|
*
|
|
* @param string url
|
|
* @return bool
|
|
*/
|
|
Rhymix.isSameHost = function(url) {
|
|
if (typeof url !== 'string') {
|
|
return false;
|
|
}
|
|
if (url.match(/^\.?\/[^\/]/)) {
|
|
return true;
|
|
}
|
|
if (url.match(/^\w+:[^\/]*$/) || url.match(/^(https?:)?\/\/[^\/]*[^a-z0-9\/.:_-]/i)) {
|
|
return false;
|
|
}
|
|
if (!this.state.partialOrigin) {
|
|
let uri = this.URI(window.request_uri).normalizePort().normalizeHostname().normalizePathname();
|
|
this.state.partialOrigin = uri.hostname() + uri.directory();
|
|
}
|
|
try {
|
|
let target_url = this.URI(url).normalizePort().normalizeHostname().normalizePathname();
|
|
if (target_url.is('urn')) {
|
|
return false;
|
|
}
|
|
if (!target_url.hostname()) {
|
|
target_url = target_url.absoluteTo(window.request_uri);
|
|
}
|
|
target_url = target_url.hostname() + target_url.directory();
|
|
return target_url.indexOf(this.state.partialOrigin) === 0;
|
|
} catch(err) {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Redirect to a URL, but reload instead if the target is the same as the current page
|
|
*
|
|
* @param string url
|
|
* @return void
|
|
*/
|
|
Rhymix.redirectToUrl = function(url) {
|
|
if (this.isCurrentUrl(url)) {
|
|
window.location.href = url;
|
|
window.location.reload();
|
|
} else {
|
|
window.location.href = url;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Open a new window and focus it
|
|
*
|
|
* @param string url
|
|
* @param string target
|
|
* @param string features
|
|
* @return void
|
|
*/
|
|
Rhymix.openWindow = function(url, target, features) {
|
|
|
|
// Fill default values
|
|
if (typeof target === 'undefined') {
|
|
target = '_blank';
|
|
}
|
|
if (typeof features === 'undefined') {
|
|
features = '';
|
|
}
|
|
|
|
// Close any existing window with the same target name
|
|
try {
|
|
if (target !== '_blank' && this.openWindowList[target]) {
|
|
this.openWindowList[target].close();
|
|
delete this.openWindowList[target];
|
|
}
|
|
} catch(e) {}
|
|
|
|
// Open using Blankshield if the target is a different site
|
|
if (!this.isSameHost(url)) {
|
|
window.blankshield.open(url, target, features);
|
|
} else {
|
|
const win = window.open(url, target, features);
|
|
win.focus();
|
|
if (target !== '_blank') {
|
|
this.openWindowList[target] = win;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Open a popup with standard features, for backward compatibility
|
|
*
|
|
* @param string url
|
|
* @param string target
|
|
* @return void
|
|
*/
|
|
Rhymix.openPopup = function(url, target) {
|
|
const features = 'width=800,height=600,toolbars=no,scrollbars=yes,resizable=yes';
|
|
this.openWindow(url, target, features);
|
|
};
|
|
|
|
/**
|
|
* Save background scroll position
|
|
*
|
|
* @param bool pushState
|
|
* @return void
|
|
*/
|
|
Rhymix.modal.saveBackgroundPosition = function(modal_id, pushState) {
|
|
const body = $(document.body);
|
|
if (!body.data('rx_scroll_position')) {
|
|
body.data('rx_scroll_position', {
|
|
left: $(window).scrollLeft(),
|
|
top: $(window).scrollTop()
|
|
});
|
|
}
|
|
body.addClass('rx_modal_open');
|
|
if (pushState) {
|
|
history.pushState({ modal: modal_id }, '', location.href);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Open an HTML element as a modal
|
|
*
|
|
* @param string id
|
|
* @return void
|
|
*/
|
|
Rhymix.modal.open = function(id) {
|
|
this.saveBackgroundPosition(id, true);
|
|
$('#' + id).addClass('active');
|
|
};
|
|
|
|
/**
|
|
* Open an iframe as a modal
|
|
*
|
|
* @param string url
|
|
* @param string target
|
|
* @return void
|
|
*/
|
|
Rhymix.modal.openIframe = function(url, target) {
|
|
const iframe = document.createElement('iframe');
|
|
const iframe_sequence = String(Date.now()) + Math.round(Math.random() * 1000000);
|
|
const iframe_id = '_rx_iframe_' + iframe_sequence;
|
|
iframe.setAttribute('id', iframe_id);
|
|
iframe.setAttribute('class', 'rx_modal');
|
|
iframe.setAttribute('name', target || ('_rx_iframe_' + iframe_sequence))
|
|
iframe.setAttribute('src', url + '&iframe_sequence=' + iframe_sequence);
|
|
iframe.setAttribute('width', '100%');
|
|
iframe.setAttribute('height', '100%');
|
|
iframe.setAttribute('style', 'position:fixed; top:0; left:0; width:100%; height:100%; border:0; z-index:999999999; background-color: #fff; overflow-y:auto');
|
|
this.saveBackgroundPosition(iframe_id, true);
|
|
$(document.body).append(iframe);
|
|
};
|
|
|
|
/**
|
|
* Close currently open modal
|
|
*
|
|
* @param string id
|
|
* @return void
|
|
*/
|
|
Rhymix.modal.close = function(id) {
|
|
history.back();
|
|
/*
|
|
if (typeof id === 'string') {
|
|
$('#' + id).remove();
|
|
} else {
|
|
$('.rx_modal').remove();
|
|
}
|
|
*/
|
|
};
|
|
|
|
/**
|
|
* Make an AJAX request
|
|
*
|
|
* @param string action
|
|
* @param object params
|
|
* @param function success
|
|
* @param function error
|
|
* @return void
|
|
*/
|
|
Rhymix.ajax = function(action, params, success, error) {
|
|
|
|
// Extract module and act
|
|
let isFormData = params instanceof FormData;
|
|
let module, act;
|
|
if (!action) {
|
|
if (isFormData) {
|
|
module = params.get('module');
|
|
act = params.get('act');
|
|
if (module && act) {
|
|
action = module + '.' + act;
|
|
} else if (act) {
|
|
action = act;
|
|
} else {
|
|
action = null;
|
|
}
|
|
} 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 (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 = {
|
|
'X-CSRF-Token': getCSRFToken()
|
|
};
|
|
if (isFormData && params.has('_rx_csrf_token') && params.get('_rx_csrf_token') === headers['X-CSRF-Token']) {
|
|
params.delete('_rx_csrf_token');
|
|
}
|
|
if (typeof params._rx_csrf_token !== 'undefined' && params._rx_csrf_token === headers['X-CSRF-Token']) {
|
|
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);
|
|
}
|
|
};
|
|
|
|
// Send the AJAX request
|
|
try {
|
|
$.ajax(args);
|
|
} catch(e) {
|
|
alert(e);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
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 a success callback was defined, call it.
|
|
if ($.isFunction(success)) {
|
|
success(data, xhr);
|
|
return;
|
|
}
|
|
|
|
// If the response contains a redirect URL, follow the redirect.
|
|
if (data.redirect_url) {
|
|
this.redirectToUrl(data.redirect_url.replace(/&/g, '&'));
|
|
return;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 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) {
|
|
|
|
// If the user is navigating away, don't do anything.
|
|
if (xhr.status == 0 && this.unloading) {
|
|
return;
|
|
}
|
|
|
|
// 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. Abort if it returns false.
|
|
if ($.isFunction(error)) {
|
|
let fakedata = { error: -3, message: textStatus };
|
|
if (error(fakedata, xhr) === false) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 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) + '...';
|
|
}
|
|
|
|
// 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());
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Submit a form using AJAX instead of navigating away
|
|
*
|
|
* @param HTMLElement form
|
|
* @param function success
|
|
* @param function error
|
|
* @return void
|
|
*/
|
|
Rhymix.ajaxForm = function(form, success, error) {
|
|
const $form = $(form);
|
|
// Get success and error callback functions.
|
|
if (typeof success === 'undefined') {
|
|
success = $form.data('callbackSuccess');
|
|
if (success && $.isFunction(success)) {
|
|
// no-op
|
|
} else if (success && window[success] && $.isFunction(window[success])) {
|
|
success = window[success];
|
|
} else {
|
|
success = function(data) {
|
|
if (data.message && data.message !== 'success') {
|
|
alert(data.message);
|
|
}
|
|
if (data.redirect_url) {
|
|
Rhymix.redirectToUrl(data.redirect_url.replace(/&/g, '&'));
|
|
}
|
|
};
|
|
}
|
|
}
|
|
if (typeof error === 'undefined') {
|
|
error = $form.data('callbackError');
|
|
if (error && $.isFunction(error)) {
|
|
// no-op
|
|
} else if (error && window[error] && $.isFunction(window[error])) {
|
|
error = window[error];
|
|
} else {
|
|
error = null;
|
|
}
|
|
}
|
|
this.ajax(null, new FormData($form[0]), success, error);
|
|
};
|
|
|
|
/**
|
|
* Toggle all checkboxes that have the same name
|
|
*
|
|
* This is a legacy function. Do not write new code that relies on it.
|
|
*
|
|
* @param string name
|
|
* @return void
|
|
*/
|
|
Rhymix.checkboxToggleAll = function(name) {
|
|
if (!window[name]) {
|
|
name='cart';
|
|
}
|
|
let options = {
|
|
wrap : null,
|
|
checked : 'toggle',
|
|
doClick : false
|
|
};
|
|
|
|
if (arguments.length == 1) {
|
|
if(typeof(arguments[0]) == 'string') {
|
|
name = arguments[0];
|
|
} else {
|
|
$.extend(options, arguments[0] || {});
|
|
name = 'cart';
|
|
}
|
|
} else {
|
|
name = arguments[0];
|
|
$.extend(options, arguments[1] || {});
|
|
}
|
|
|
|
if (options.doClick === true) {
|
|
options.checked = null;
|
|
}
|
|
if (typeof options.wrap === 'string') {
|
|
options.wrap = '#' + options.wrap;
|
|
}
|
|
|
|
let obj;
|
|
if (options.wrap) {
|
|
obj = $(options.wrap).find('input[name="'+name+'"]:checkbox');
|
|
} else {
|
|
obj = $('input[name="'+name+'"]:checkbox');
|
|
}
|
|
|
|
if (options.checked === 'toggle') {
|
|
obj.each(function() {
|
|
$(this).prop('checked', $(this).prop('checked') ? false : true);
|
|
});
|
|
} else {
|
|
if(options.doClick === true) {
|
|
obj.click();
|
|
} else {
|
|
obj.prop('checked', options.checked);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Display a popup menu for members, documents, etc.
|
|
*
|
|
* @param object ret_obj
|
|
* @param object response_tags
|
|
* @param object params
|
|
* @return void
|
|
*/
|
|
Rhymix.displayPopupMenu = function(ret_obj, response_tags, params) {
|
|
const menu_id = params.menu_id;
|
|
const menus = ret_obj.menus;
|
|
let html = "";
|
|
|
|
if (this.loadedPopupMenus[menu_id]) {
|
|
html = this.loadedPopupMenus[menu_id];
|
|
} else {
|
|
if (menus) {
|
|
let item = menus.item || menus;
|
|
if (typeof item.length === 'undefined' || item.length < 1) {
|
|
item = new Array(item);
|
|
}
|
|
if (item.length) {
|
|
for (let i = 0; i < item.length; i++) {
|
|
var url = item[i].url;
|
|
var str = item[i].str;
|
|
var classname = item[i]['class'];
|
|
var icon = item[i].icon;
|
|
var target = item[i].target;
|
|
|
|
// Convert self to _self #2154
|
|
if (target === 'self') {
|
|
target = '_self';
|
|
}
|
|
|
|
var actmatch = url.match(/\bact=(\w+)/) || url.match(/\b((?:disp|proc)\w+)/);
|
|
var act = actmatch ? actmatch[1] : null;
|
|
var classText = 'class="' + (classname ? classname : (act ? (act + ' ') : ''));
|
|
var styleText = "";
|
|
var click_str = "";
|
|
var matches = [];
|
|
if (target === 'popup') {
|
|
if (this.isMobile()) {
|
|
click_str = 'onclick="openModalIframe(this.href, \''+target+'\'); return false;"';
|
|
} else {
|
|
click_str = 'onclick="popopen(this.href, \''+target+'\'); return false;"';
|
|
}
|
|
classText += 'popup ';
|
|
} else if (target === 'javascript') {
|
|
click_str = 'onclick="'+url+'; return false; "';
|
|
classText += 'javascript ';
|
|
url = '#';
|
|
} else if (target.match(/^_(self|blank|parent|top)$/)) {
|
|
click_str = 'target="' + target + '"';
|
|
classText += 'frame_' + target + ' ';
|
|
} else if (matches = target.match(/^i?frame:([a-zA-Z0-9_]+)$/)) {
|
|
click_str = 'target="' + matches[1] + '"';
|
|
classText += 'frame_' + matches[1] + ' ';
|
|
} else {
|
|
click_str = 'target="_blank"';
|
|
}
|
|
classText = classText.trim() + '" ';
|
|
|
|
html += '<li '+classText+styleText+'><a href="'+url+'" '+click_str+'>'+str+'</a></li> ';
|
|
}
|
|
}
|
|
}
|
|
this.loadedPopupMenus[menu_id] = html;
|
|
}
|
|
|
|
/* 레이어 출력 */
|
|
if (html) {
|
|
const area = $('#popup_menu_area').html('<ul>'+html+'</ul>');
|
|
const areaOffset = {top:params.page_y, left:params.page_x};
|
|
if (area.outerHeight()+areaOffset.top > $(window).height()+$(window).scrollTop()) {
|
|
areaOffset.top = $(window).height() - area.outerHeight() + $(window).scrollTop();
|
|
}
|
|
if (area.outerWidth()+areaOffset.left > $(window).width()+$(window).scrollLeft()) {
|
|
areaOffset.left = $(window).width() - area.outerWidth() + $(window).scrollLeft();
|
|
}
|
|
area.css({ top:areaOffset.top, left:areaOffset.left }).show().focus();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Format file size
|
|
*
|
|
* @param int size
|
|
* @return string
|
|
*/
|
|
Rhymix.filesizeFormat = function(size) {
|
|
if (size < 2) {
|
|
return size + 'Byte';
|
|
}
|
|
if (size < 1024) {
|
|
return size + 'Bytes';
|
|
}
|
|
if (size < 1048576) {
|
|
return (size / 1024).toFixed(1) + 'KB';
|
|
}
|
|
if (size < 1073741824) {
|
|
return (size / 1048576).toFixed(2) + 'MB';
|
|
}
|
|
if (size < 1099511627776) {
|
|
return (size / 1073741824).toFixed(2) + 'GB';
|
|
}
|
|
return (size / 1099511627776).toFixed(2) + 'TB';
|
|
};
|
|
|
|
/**
|
|
* Get or set a lang code
|
|
*
|
|
* @param string key
|
|
* @param string val
|
|
* @return string|void
|
|
*/
|
|
Rhymix.lang = function(key, val) {
|
|
if (typeof val === 'undefined') {
|
|
return this.langCodes[key] || key;
|
|
} else {
|
|
return this.langCodes[key] = val;
|
|
}
|
|
};
|
|
|
|
// Add aliases to loaded libraries
|
|
Rhymix.cookie = window.Cookies;
|
|
Rhymix.URI = window.URI;
|
|
Rhymix.URITemplate = window.URITemplate;
|
|
Rhymix.SecondLevelDomains = window.SecondLevelDomains;
|
|
Rhymix.IPv6 = window.IPv6;
|
|
|
|
// Set window properties for backward compatibility
|
|
const XE = window.XE = Rhymix;
|
|
|
|
/**
|
|
* ============================
|
|
* Document ready event handler
|
|
* ============================
|
|
*/
|
|
|
|
$(function() {
|
|
|
|
/**
|
|
* Inject CSRF token to all POST forms
|
|
*/
|
|
$('form[method]').filter(function() {
|
|
return String($(this).attr('method')).toUpperCase() == 'POST';
|
|
}).addCSRFTokenToForm();
|
|
$(document).on('submit', 'form[method=post]', $.fn.addCSRFTokenToForm);
|
|
$(document).on('focus', 'input,select,textarea', function() {
|
|
$(this).parents('form[method]').filter(function() {
|
|
return String($(this).attr('method')).toUpperCase() == 'POST';
|
|
}).addCSRFTokenToForm();
|
|
});
|
|
|
|
/**
|
|
* Reverse tabnapping protection
|
|
*
|
|
* Automatically add rel="noopener" to any external link with target="_blank"
|
|
* This is not required in most modern browsers.
|
|
* https://caniuse.com/mdn-html_elements_a_implicit_noopener
|
|
*/
|
|
const noopenerRequired = (function() {
|
|
const isChromeBased = navigator.userAgent.match(/Chrome\/([0-9]+)/);
|
|
if (isChromeBased && parseInt(isChromeBased[1], 10) >= 72) {
|
|
return false;
|
|
}
|
|
const isAppleWebKit = navigator.userAgent.match(/AppleWebKit\/([0-9]+)/);
|
|
if (isAppleWebKit && parseInt(isAppleWebKit[1], 10) >= 605) {
|
|
return false;
|
|
}
|
|
const isFirefox = navigator.userAgent.match(/Firefox\/([0-9]+)/);
|
|
if (isFirefox && parseInt(isFirefox[1], 10) >= 79) {
|
|
return false;
|
|
}
|
|
return true;
|
|
})();
|
|
$('a[target]').each(function() {
|
|
const $this = $(this);
|
|
const href = String($this.attr('href')).trim();
|
|
const target = String($this.attr('target')).trim();
|
|
if (!href || !target || target === '_top' || target === '_self' || target === '_parent') {
|
|
return;
|
|
}
|
|
if (!Rhymix.isSameHost(href)) {
|
|
let rel = $this.attr('rel');
|
|
rel = (typeof rel === 'undefined') ? '' : String(rel);
|
|
if (!rel.match(/\bnoopener\b/)) {
|
|
$this.attr('rel', $.trim(rel + ' noopener'));
|
|
}
|
|
}
|
|
});
|
|
$(document).on('click', 'a[target]', function(event) {
|
|
const $this = $(this);
|
|
const href = String($this.attr('href')).trim();
|
|
const target = String($this.attr('target')).trim();
|
|
if (!href || !target || target === '_top' || target === '_self' || target === '_parent') {
|
|
return;
|
|
}
|
|
if (!Rhymix.isSameHost(href)) {
|
|
let rel = $this.attr('rel');
|
|
rel = (typeof rel === 'undefined') ? '' : String(rel);
|
|
if (!rel.match(/\bnoopener\b/)) {
|
|
$this.attr('rel', $.trim(rel + ' noopener'));
|
|
}
|
|
if (noopenerRequired) {
|
|
event.preventDefault();
|
|
blankshield.open(href);
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Enforce max filesize on file uploaeds
|
|
*/
|
|
$(document).on('change', 'input[type=file]', function() {
|
|
const max_filesize = $(this).data('max-filesize');
|
|
if (!max_filesize) {
|
|
return;
|
|
}
|
|
const files = $(this).get(0).files;
|
|
if (!files || !files[0]) {
|
|
return;
|
|
}
|
|
if (files[0].size > max_filesize) {
|
|
this.value = '';
|
|
const error = String($(this).data('max-filesize-error'));
|
|
alert(error.replace('%s', Rhymix.filesizeFormat(max_filesize)));
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Intercept form submission and handle them with AJAX
|
|
*/
|
|
$(document).on('submit', 'form.rx_ajax', function(event) {
|
|
if (!$(this).attr('target')) {
|
|
event.preventDefault();
|
|
Rhymix.ajaxForm(this);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Prevent repeated click on submit button
|
|
*/
|
|
$(document).on('click', 'input[type="submit"],button[type="submit"]', function(e) {
|
|
const timeout = 3000;
|
|
setTimeout(function() {
|
|
$(this).prop('disabled', true);
|
|
}, 100);
|
|
setTimeout(function() {
|
|
$(this).prop('disabled', false);
|
|
}, timeout);
|
|
});
|
|
|
|
/**
|
|
* Display a popup menu for members, documents, etc.
|
|
*/
|
|
$(document).on('click', function(e) {
|
|
var $area = $('#popup_menu_area');
|
|
if (!$area.length) {
|
|
$area = $('<div id="popup_menu_area" tabindex="0" style="display:none;" />').appendTo(document.body);
|
|
}
|
|
|
|
// 이전에 호출되었을지 모르는 팝업메뉴 숨김
|
|
$area.hide();
|
|
|
|
var $target = $(e.target).filter('a,div,span');
|
|
if (!$target.length) {
|
|
$target = $(e.target).closest('a,div,span');
|
|
}
|
|
if (!$target.length) {
|
|
return;
|
|
}
|
|
|
|
// 객체의 className값을 구함
|
|
var cls = $target.attr('class'), match;
|
|
if (cls) {
|
|
match = cls.match(new RegExp('(?:^| )((document|comment|member)_([1-9][0-9]*))(?: |$)',''));
|
|
}
|
|
if (!match) {
|
|
return;
|
|
}
|
|
|
|
// mobile에서 touchstart에 의한 동작 시 pageX, pageY 위치를 구함
|
|
if (e.pageX === undefined || e.pageY === undefined)
|
|
{
|
|
let touch = e.originalEvent.touches[0];
|
|
if (touch !== undefined || !touch) {
|
|
touch = e.originalEvent.changedTouches[0];
|
|
}
|
|
e.pageX = touch.pageX;
|
|
e.pageY = touch.pageY;
|
|
}
|
|
|
|
var module = match[2];
|
|
var action = 'get' + ucfirst(module) + 'Menu';
|
|
var target_srl = match[3];
|
|
var params = {
|
|
mid : current_mid,
|
|
cur_mid : current_mid,
|
|
menu_id : match[1],
|
|
target_srl : target_srl,
|
|
cur_act : current_url.getQuery('act'),
|
|
page_x : e.pageX,
|
|
page_y : e.pageY
|
|
};
|
|
var response_tags = ['error', 'message', 'menus'];
|
|
|
|
// prevent default action
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
if (window[Rhymix.loadedPopupMenus[params.menu_id]]) {
|
|
return Rhymix.displayPopupMenu(params, response_tags, params);
|
|
}
|
|
|
|
show_waiting_message = false;
|
|
exec_json(module + '.' + action, params, function(data) {
|
|
Rhymix.displayPopupMenu(data, response_tags, params);
|
|
show_waiting_message = true;
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Create popup windows automatically for _xe_popup links
|
|
*/
|
|
$(document).on('click', 'a._xe_popup', function(e) {
|
|
var $this = $(this);
|
|
var name = $this.attr('name');
|
|
var href = $this.attr('href');
|
|
if (!name) {
|
|
name = '_xe_popup_' + Math.floor(Math.random() * 1000);
|
|
}
|
|
e.preventDefault();
|
|
winopen(href, name, 'left=10,top=10,width=10,height=10,resizable=no,scrollbars=no,toolbars=no');
|
|
});
|
|
|
|
/**
|
|
* Editor preview replacement
|
|
*/
|
|
const editable_previews = $('.editable_preview');
|
|
editable_previews.addClass('rhymix_content xe_content').attr('tabindex', 0);
|
|
editable_previews.on('click', function() {
|
|
let input = $(this).siblings('.editable_preview_content');
|
|
if (input.size()) {
|
|
$(this).off('click').off('focus').hide();
|
|
input = input.first();
|
|
if (input.attr('type') !== 'hidden') {
|
|
input.hide();
|
|
}
|
|
let iframe = $('<iframe class="editable_preview_iframe"></iframe>');
|
|
iframe.attr('src', current_url.setQuery('module', 'editor').setQuery('act', 'dispEditorFrame').setQuery('parent_input_id', input.attr('id')).replace(/^https?:/, ''));
|
|
iframe.insertAfter(input);
|
|
}
|
|
});
|
|
editable_previews.on('focus', function() {
|
|
$(this).triggerHandler('click');
|
|
});
|
|
|
|
/**
|
|
* Datepicker default settings
|
|
*/
|
|
if ($.datepicker) {
|
|
$.datepicker.setDefaults({
|
|
dateFormat : 'yy-mm-dd'
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Display any pending alert messages
|
|
*/
|
|
if(Cookies.get('rhymix_alert_message')) {
|
|
rhymix_alert(Cookies.get('rhymix_alert_message'), null, Cookies.get('rhymix_alert_delay'));
|
|
Cookies.remove('rhymix_alert_message', { path: '/' });
|
|
Cookies.remove('rhymix_alert_delay', { path: '/' });
|
|
}
|
|
$('#rhymix_alert').on('click', rhymix_alert_close);
|
|
|
|
});
|
|
|
|
/**
|
|
* ====================
|
|
* Other event handlers
|
|
* ====================
|
|
*/
|
|
|
|
// Intercept getScript error due to broken minified script URLs
|
|
$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
|
|
if(settings.dataType === "script" && (jqxhr.status >= 400 || (jqxhr.responseText && jqxhr.responseText.length < 40))) {
|
|
const match = /^(.+)\.min\.(css|js)($|\?)/.exec(settings.url);
|
|
if(match) {
|
|
$.getScript(match[1] + "." + match[2], settings.success);
|
|
}
|
|
}
|
|
});
|
|
|
|
// General handler for page unload events
|
|
window.addEventListener('beforeunload', function() {
|
|
Rhymix.unloading = true;
|
|
});
|
|
|
|
// General handler for popstate events
|
|
window.addEventListener('popstate', function(event) {
|
|
// Close modal if it is open
|
|
if ($(document.body).hasClass('rx_modal_open')) {
|
|
const body = $(document.body).removeClass('rx_modal_open');
|
|
const scroll_position = body.data('rx_scroll_position');
|
|
if (scroll_position) {
|
|
$(window).scrollLeft(scroll_position.left);
|
|
$(window).scrollTop(scroll_position.top);
|
|
body.removeData('rx_scroll_position');
|
|
}
|
|
$('.rx_modal').each(function() {
|
|
if (this.nodeName === 'IFRAME') {
|
|
$(this).remove();
|
|
} else {
|
|
$(this).removeClass('active');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* =================
|
|
* jQuery extensions
|
|
* =================
|
|
*/
|
|
|
|
(function($) {
|
|
|
|
// OS check
|
|
const UA = navigator.userAgent.toLowerCase();
|
|
$.os = {
|
|
Windows: /win/.test(UA),
|
|
Android: /android/.test(UA),
|
|
iOS: /i(Phone|Pad)/.test(UA),
|
|
Linux: /linux/.test(UA),
|
|
Unix: /x11/.test(UA),
|
|
Mac: /mac/.test(UA)
|
|
};
|
|
$.os.name = ($.os.Windows) ? 'Windows' :
|
|
($.os.Android) ? 'Android' :
|
|
($.os.iOS) ? 'iOS' :
|
|
($.os.Linux) ? 'Linux' :
|
|
($.os.Unix) ? 'Unix' :
|
|
($.os.Mac) ? 'Mac' : '';
|
|
|
|
// Add CSRF token to AJAX calls
|
|
$.ajaxPrefilter(function(options) {
|
|
if (!Rhymix.isSameOrigin(location.href, options.url)) {
|
|
return;
|
|
}
|
|
const token = Rhymix.getCSRFToken();
|
|
if (token) {
|
|
if (!options.headers) {
|
|
options.headers = {};
|
|
}
|
|
options.headers['X-CSRF-Token'] = token;
|
|
}
|
|
});
|
|
|
|
// Add CSRF token to dynamically loaded forms
|
|
$.fn.addCSRFTokenToForm = function() {
|
|
const form = $(this);
|
|
const token = Rhymix.getCSRFToken();
|
|
if (token) {
|
|
return form.each(function() {
|
|
if (form.data('csrf-token-checked')) return;
|
|
if (form.attr('action') && !Rhymix.isSameOrigin(location.href, form.attr('action'))) {
|
|
return form.data('csrf-token-checked', true);
|
|
}
|
|
$('<input type="hidden" name="_rx_csrf_token" />').val(token).appendTo(form);
|
|
return form.data('csrf-token-checked', true);
|
|
});
|
|
} else {
|
|
return form;
|
|
}
|
|
};
|
|
|
|
})(jQuery);
|
|
|
|
/**
|
|
* =================
|
|
* String extensions
|
|
* =================
|
|
*/
|
|
|
|
/**
|
|
* Get a query parameter from a URL
|
|
*
|
|
* @param string key
|
|
* @return string
|
|
*/
|
|
String.prototype.getQuery = function(key) {
|
|
const queries = Rhymix.URI(this).search(true);
|
|
const result = queries[key];
|
|
if(typeof result === 'undefined') {
|
|
return '';
|
|
} else {
|
|
return result;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Add or replace a query parameter in a URL
|
|
*
|
|
* @param string key
|
|
* @param string val
|
|
* @return string
|
|
*/
|
|
String.prototype.setQuery = function(key, val) {
|
|
const uri = Rhymix.URI(this);
|
|
const protocol = window.enforce_ssl ? 'https' : uri.protocol();
|
|
const port = (protocol === 'http') ? window.http_port : window.https_port;
|
|
let filename = uri.filename() || 'index.php';
|
|
let queries = uri.search(true);
|
|
|
|
if(typeof key !== 'undefined') {
|
|
if(typeof val === "undefined" || val === '' || val === null) {
|
|
uri.removeSearch(key);
|
|
} else {
|
|
uri.setSearch(key, String(val));
|
|
}
|
|
}
|
|
|
|
if (Rhymix.isSameHost(uri.toString()) && filename === 'index.php' && $.isEmptyObject(queries)) {
|
|
filename = '';
|
|
}
|
|
|
|
return uri.protocol(protocol).port(port || null).normalizePort().filename(filename).toString();
|
|
};
|
|
|
|
/**
|
|
* Escape a string for HTML output
|
|
*
|
|
* @param bool double_escape
|
|
* @return string
|
|
*/
|
|
String.prototype.escape = function(double_escape) {
|
|
const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' };
|
|
const revmap = { '&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '"', "&#039;": ''' };
|
|
const result = String(this).replace(/[&<>"']/g, function(m) { return map[m]; });
|
|
if (double_escape === false) {
|
|
return result.replace(/&(amp|lt|gt|quot|#039);/g, function(m) { return revmap[m]; });
|
|
} else {
|
|
return result;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Unescape a string from HTML output
|
|
*
|
|
* @return string
|
|
*/
|
|
String.prototype.unescape = function() {
|
|
const map = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'" };
|
|
return String(this).replace(/&(amp|lt|gt|quot|#039);/g, function(m) { return map[m]; });
|
|
};
|
|
|
|
/**
|
|
* Strip HTML tags from a string
|
|
*
|
|
* @return string
|
|
*/
|
|
String.prototype.stripTags = function() {
|
|
return String(this).replace(/<\/?[a-z][^>]*>/ig, "");
|
|
};
|
|
|
|
/**
|
|
* Trim whitespace from the beginning and end of a string
|
|
*
|
|
* @return string
|
|
*/
|
|
if (!String.prototype.trim) {
|
|
String.prototype.trim = function() {
|
|
return String(this).replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
|
};
|
|
}
|
|
|
|
/**
|
|
* ==============================================================
|
|
* Global functions (most of these are aliases to Rhymix methods)
|
|
* ==============================================================
|
|
*/
|
|
|
|
/**
|
|
* Check if the current device is a mobile device.
|
|
*
|
|
* @return bool
|
|
*/
|
|
function isMobile() {
|
|
return Rhymix.isMobile();
|
|
}
|
|
|
|
/**
|
|
* Get the current color scheme
|
|
*
|
|
* @return string
|
|
*/
|
|
function getColorScheme() {
|
|
return Rhymix.getColorScheme();
|
|
}
|
|
|
|
/**
|
|
* Set the color scheme
|
|
*
|
|
* @param string color_scheme
|
|
* @return void
|
|
*/
|
|
function setColorScheme(color_scheme) {
|
|
return Rhymix.setColorScheme(color_scheme);
|
|
}
|
|
|
|
/**
|
|
* Automatically detect the color scheme
|
|
*
|
|
* @return void
|
|
*/
|
|
function detectColorScheme() {
|
|
return Rhymix.detectColorScheme();
|
|
}
|
|
|
|
/**
|
|
* Get the language
|
|
*
|
|
* @return string
|
|
*/
|
|
function getLangType() {
|
|
return Rhymix.getLangType();
|
|
}
|
|
|
|
/**
|
|
* Set the language
|
|
*
|
|
* @param string lang_type
|
|
* @return void
|
|
*/
|
|
function setLangType(lang_type) {
|
|
return Rhymix.setLangType(lang_type);
|
|
}
|
|
|
|
/**
|
|
* Get CSRF token for this document
|
|
*
|
|
* @return string|null
|
|
*/
|
|
function getCSRFToken() {
|
|
return Rhymix.getCSRFToken();
|
|
}
|
|
|
|
/**
|
|
* Set CSRF token for this document
|
|
*
|
|
* @param string token
|
|
* @return void
|
|
*/
|
|
function setCSRFToken(token) {
|
|
return Rhymix.setCSRFToken(token);
|
|
}
|
|
|
|
/**
|
|
* Check if a URL is identical to the current page URL except for the hash
|
|
*
|
|
* @param string url
|
|
* @return bool
|
|
*/
|
|
function isCurrentPageUrl(url) {
|
|
return Rhymix.isCurrentUrl(url);
|
|
}
|
|
|
|
/**
|
|
* Check if two URLs belong to the same origin
|
|
*
|
|
* @param string url1
|
|
* @param string url2
|
|
* @return bool
|
|
*/
|
|
function isSameOrigin(url1, url2) {
|
|
return Rhymix.isSameOrigin(url1, url2);
|
|
}
|
|
|
|
/**
|
|
* Redirect to a URL, but reload instead if the target is the same as the current page
|
|
*
|
|
* @param string url
|
|
* @return void
|
|
*/
|
|
function redirect(url) {
|
|
return Rhymix.redirectToUrl(url);
|
|
}
|
|
|
|
/**
|
|
* Open an HTML element as a modal
|
|
*
|
|
* @param string id
|
|
* @return void
|
|
*/
|
|
function openModal(id) {
|
|
return Rhymix.modal.open(id);
|
|
}
|
|
|
|
/**
|
|
* Open an iframe as a modal
|
|
*
|
|
* @param string url
|
|
* @param string target
|
|
* @return void
|
|
*/
|
|
function openModalIframe(url, target) {
|
|
return Rhymix.modal.openIframe(url, target);
|
|
}
|
|
|
|
/**
|
|
* Close currently open modal
|
|
*
|
|
* @param string id
|
|
* @return void
|
|
*/
|
|
function closeModal(id) {
|
|
return Rhymix.modal.close(id);
|
|
}
|
|
|
|
/**
|
|
* Open a new window and focus it
|
|
*
|
|
* @param string url
|
|
* @param string target
|
|
* @param string features
|
|
*/
|
|
function winopen(url, target, features) {
|
|
return Rhymix.openWindow(url, target, features);
|
|
}
|
|
|
|
/**
|
|
* Open a popup window with standardized features
|
|
*
|
|
* @param string url
|
|
* @param string target
|
|
* @return void
|
|
*/
|
|
function popopen(url, target) {
|
|
return Rhymix.openPopup(url, target);
|
|
}
|
|
|
|
/**
|
|
* ===============================================
|
|
* Legacy functions related to document management
|
|
* ===============================================
|
|
*/
|
|
|
|
/**
|
|
* Add a document to the cart for admin action.
|
|
*
|
|
* @param object obj
|
|
* @return void
|
|
*/
|
|
function doAddDocumentCart(obj) {
|
|
Rhymix.addedDocument.push(obj.value);
|
|
setTimeout(function() {
|
|
exec_json('document.procDocumentAddCart', {
|
|
srls: Rhymix.addedDocument.join(',')
|
|
});
|
|
Rhymix.addedDocument = [];
|
|
}, 100);
|
|
}
|
|
|
|
/**
|
|
* Open a document preview
|
|
*
|
|
* @param object obj
|
|
* @return void
|
|
*/
|
|
function doDocumentPreview(obj) {
|
|
var fo_obj = obj;
|
|
while (fo_obj.nodeName != "FORM") {
|
|
fo_obj = fo_obj.parentNode;
|
|
}
|
|
if (fo_obj.nodeName != "FORM") {
|
|
return;
|
|
}
|
|
|
|
var editor_sequence = fo_obj.getAttribute('editor_sequence');
|
|
var content = editorGetContent(editor_sequence);
|
|
var win = window.open("", "previewDocument","toolbars=no,width=700px;height=800px,scrollbars=yes,resizable=yes");
|
|
var dummy_obj = $("#previewDocument");
|
|
if (!dummy_obj.length) {
|
|
$(
|
|
'<form id="previewDocument" target="previewDocument" method="post" action="'+request_uri+'">'+
|
|
'<input type="hidden" name="_rx_csrf_token" value="' + getCSRFToken() + '" />'+
|
|
'<input type="hidden" name="module" value="document" />'+
|
|
'<input type="hidden" name="act" value="dispDocumentPreview" />'+
|
|
'<input type="hidden" name="mid" value="' + current_mid +'" />'+
|
|
'<input type="hidden" name="content" />'+
|
|
'</form>'
|
|
).appendTo(document.body);
|
|
dummy_obj = $("#previewDocument")[0];
|
|
} else {
|
|
dummy_obj = dummy_obj[0];
|
|
}
|
|
|
|
if(dummy_obj) {
|
|
dummy_obj.content.value = content;
|
|
dummy_obj.submit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Temporarily save a document
|
|
*
|
|
* @param object obj
|
|
* @returns
|
|
*/
|
|
function doDocumentSave(obj) {
|
|
var editor_sequence = obj.form.getAttribute('editor_sequence');
|
|
var prev_content = editorRelKeys[editor_sequence].content.value;
|
|
if (typeof(editor_sequence) !== 'undefined' && editor_sequence && typeof(editorRelKeys) !== 'undefined' && typeof(editorGetContent) === 'function') {
|
|
var content = editorGetContent(editor_sequence);
|
|
editorRelKeys[editor_sequence].content.value = content;
|
|
}
|
|
|
|
var params={}, data=$(obj.form).serializeArray();
|
|
$.each(data, function(i, field){
|
|
var val = $.trim(field.value);
|
|
if (!val) {
|
|
return true;
|
|
}
|
|
if (/\[\]$/.test(field.name)) {
|
|
field.name = field.name.replace(/\[\]$/, '');
|
|
}
|
|
if (params[field.name]) {
|
|
params[field.name] += '|@|'+val;
|
|
} else {
|
|
params[field.name] = field.value;
|
|
}
|
|
});
|
|
|
|
exec_json('document.procDocumentTempSave', params, function(ret_obj) {
|
|
$('input[name=document_srl]').eq(0).val(ret_obj.document_srl);
|
|
alert(ret_obj.message);
|
|
});
|
|
|
|
editorRelKeys[editor_sequence].content.value = prev_content;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Load the list of saved documents
|
|
*/
|
|
function doDocumentLoad(obj) {
|
|
var popup_url = request_uri.setQuery('module','document').setQuery('act','dispTempSavedList');
|
|
if (Rhymix.isMobile()) {
|
|
openModalIframe(popup_url);
|
|
} else {
|
|
popopen(popup_url);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Select from the list of saved documents
|
|
*
|
|
* @param int document_srl
|
|
* @param string module
|
|
* @return void
|
|
*/
|
|
function doDocumentSelect(document_srl, module) {
|
|
if (!opener) {
|
|
window.close();
|
|
return;
|
|
}
|
|
if (module === undefined) {
|
|
module = 'document';
|
|
}
|
|
|
|
// 게시글을 가져와서 등록하기
|
|
if (module === 'page') {
|
|
var url = opener.current_url;
|
|
url = url.setQuery('document_srl', document_srl);
|
|
if (url.getQuery('act') === 'dispPageAdminMobileContentModify') {
|
|
url = url.setQuery('act', 'dispPageAdminMobileContentModify');
|
|
} else {
|
|
url = url.setQuery('act', 'dispPageAdminContentModify');
|
|
}
|
|
opener.location.href = url;
|
|
} else {
|
|
opener.location.href = opener.current_url.setQuery('act', 'dispBoardWrite').setQuery('document_srl', document_srl);
|
|
}
|
|
window.close();
|
|
}
|
|
|
|
/**
|
|
* ==================================================================
|
|
* Deprecated functions (Please avoid using anything below this line)
|
|
* ==================================================================
|
|
*/
|
|
|
|
/**
|
|
* Get a cookie
|
|
*
|
|
* Use Rhymix.cookie.get() instead
|
|
*
|
|
* @deprecated
|
|
* @param string name
|
|
* @return string|null
|
|
*/
|
|
function getCookie(name) {
|
|
return Rhymix.cookie.get(name);
|
|
}
|
|
|
|
/**
|
|
* Set a cookie
|
|
*
|
|
* Use Rhymix.cookie.set() instead
|
|
*
|
|
* @deprecated
|
|
* @param string name
|
|
* @param string value
|
|
* @param int expires
|
|
* @param string path
|
|
* @return void
|
|
*/
|
|
function setCookie(name, value, expires, path) {
|
|
var options = {
|
|
path: path ? path : '/',
|
|
secure: cookies_ssl ? true : false
|
|
};
|
|
if (expires) {
|
|
options.expires = expires;
|
|
}
|
|
Rhymix.cookie.set(name, value, options);
|
|
}
|
|
|
|
/**
|
|
* Change the language and reload the page
|
|
*
|
|
* @deprecated
|
|
* @param string|object obj
|
|
* @return void
|
|
*/
|
|
function doChangeLangType(obj) {
|
|
var msg = "DEPRECATED : doChangeLangType() is deprecated in Rhymix.";
|
|
if (navigator.userAgent.match(/Firefox/)) {
|
|
console.error(msg);
|
|
} else {
|
|
console.warn(msg);
|
|
}
|
|
|
|
if (typeof(obj) == 'string') {
|
|
setLangType(obj);
|
|
} else {
|
|
setLangType(obj.options[obj.selectedIndex].value);
|
|
}
|
|
if (location.href.match(/[?&]l=[a-z]+/)) {
|
|
location.href = location.href.setQuery('l', '');
|
|
} else {
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make an AJAX request with a given target_srl
|
|
*
|
|
* Please use Rhymix.ajax() instead, which is much more powerful.
|
|
*
|
|
* @deprecated
|
|
* @param string module
|
|
* @param string action
|
|
* @param int target_rl
|
|
* @return void
|
|
*/
|
|
function doCallModuleAction(module, action, target_srl) {
|
|
var msg = "DEPRECATED : doCallModuleAction() is deprecated in Rhymix.";
|
|
if (navigator.userAgent.match(/Firefox/)) {
|
|
console.error(msg);
|
|
} else {
|
|
console.warn(msg);
|
|
}
|
|
|
|
const params = {
|
|
target_srl: target_srl,
|
|
cur_mid: current_mid,
|
|
mid: current_mid
|
|
};
|
|
Rhymix.ajax(module + '.' + action, params, function(data) {
|
|
if (data.message !== 'success') {
|
|
alert(data.message);
|
|
}
|
|
location.reload();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Close an alert box
|
|
*
|
|
* @deprecated
|
|
* @return void
|
|
*/
|
|
function rhymix_alert_close() {
|
|
if ($('#rhymix_alert').is(':hidden')) {
|
|
return;
|
|
}
|
|
$('#rhymix_alert').fadeOut(500, function() {
|
|
$(this).empty();
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Display an alert box
|
|
*
|
|
* @deprecated
|
|
* @param string message
|
|
* @param string redirect_url
|
|
* @param int delay
|
|
* @return void
|
|
*/
|
|
function rhymix_alert(message, redirect_url, delay) {
|
|
if (!delay) {
|
|
delay = 2500;
|
|
}
|
|
if (!redirect_url) {
|
|
$('#rhymix_alert').text(message).show();
|
|
setTimeout(rhymix_alert_close, delay);
|
|
} else if (Rhymix.isSameOrigin(location.href, redirect_url)) {
|
|
Cookies.set('rhymix_alert_message', message, { expires: 1 / 1440, path: '/' });
|
|
Cookies.set('rhymix_alert_delay', delay, { expires: 1 / 1440, path: '/' });
|
|
} else {
|
|
alert(message);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Move to a URL
|
|
*
|
|
* @deprecated
|
|
* @param string url
|
|
* @param string open_window
|
|
* @return bool
|
|
*/
|
|
function move_url(url, open_window) {
|
|
if (!url) {
|
|
return false;
|
|
}
|
|
if (/^\./.test(url)) {
|
|
url = window.request_uri + url;
|
|
}
|
|
if (typeof open_window == 'undefined' || open_window == 'N') {
|
|
redirect(url);
|
|
} else {
|
|
winopen(url);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Resize a popup window according to the size of its contents
|
|
*
|
|
* @deprecated
|
|
* @return void
|
|
*/
|
|
function setFixedPopupSize() {
|
|
var $win = $(window);
|
|
var $pc = $('body > .popup');
|
|
var $outer = $('<div>').css({visibility: 'hidden', width: 100, overflow: 'scroll'}).appendTo('body');
|
|
var widthWithScroll = $('<div>').css({width: '100%'}).appendTo($outer).outerWidth();
|
|
$outer.remove();
|
|
var scbw = 100 - widthWithScroll;
|
|
var offset = $pc.css({overflow: 'scroll'}).offset();
|
|
|
|
var w = $pc.width(10).height(10000).get(0).scrollWidth + offset.left*2;
|
|
if (w < 800) {
|
|
w = 800 + (offset.left * 2);
|
|
}
|
|
|
|
// window의 너비나 높이는 스크린의 너비나 높이보다 클 수 없다.
|
|
// 스크린의 너비나 높이와 내용의 너비나 높이를 비교해서 최소값을 이용한다.
|
|
w = Math.min(w, window.screen.availWidth);
|
|
var h = $pc.width(w - offset.left*2).height(10).get(0).scrollHeight + offset.top*2;
|
|
var dw = $win.width();
|
|
var dh = $win.height();
|
|
|
|
h = Math.min(h, window.screen.availHeight - 100);
|
|
window.resizeBy(w - dw, h - dh);
|
|
$pc.width('100%').css({
|
|
overflow: '',
|
|
height: '',
|
|
'box-sizing': 'border-box'
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Print a thumbnail for multimedia content
|
|
*
|
|
* @deprecated
|
|
* @param string src
|
|
* @param int width
|
|
* @param int height
|
|
* @param object options
|
|
* @return void
|
|
*/
|
|
function displayMultimedia(src, width, height, options) {
|
|
const html = _displayMultimedia(src, width, height, options);
|
|
if (html) {
|
|
document.writeln(html);
|
|
}
|
|
}
|
|
function _displayMultimedia(src, width, height, options) {
|
|
width = parseInt(width, 10);
|
|
height = parseInt(height, 10);
|
|
if (src.indexOf('files') === 0) {
|
|
src = request_uri + src;
|
|
}
|
|
|
|
var html = '';
|
|
var background = 'black';
|
|
|
|
if (/\.(gif|jpe?g|bmp|png|webp)$/i.test(src)){
|
|
html = '<img src="'+src+'" width="'+width+'" height="'+height+'" class="thumb" />';
|
|
} else {
|
|
if (options.thumbnail) {
|
|
background += " url('" + options.thumbnail + "');background-size:cover;background-position:center center";
|
|
}
|
|
html = '<span style="position:relative;background:' + background + ';width:' + width + 'px;height:' + height + 'px" class="thumb">';
|
|
html += '<img style="width:24px;height:24px;position:absolute;left:50%;top:50%;border:0;margin:-12px 0 0 -12px;padding:0" src="' + request_uri + 'common/img/play.png" alt="" />';
|
|
html += '</span>';
|
|
}
|
|
return html;
|
|
}
|
|
|
|
/**
|
|
* Convert rgb(r,g,b) to HEX
|
|
*
|
|
* @param string value
|
|
* @return string
|
|
*/
|
|
function transRGB2Hex(value) {
|
|
if (!value) {
|
|
return value;
|
|
}
|
|
if (value.indexOf('#') > -1) {
|
|
return value.replace(/^#/, '');
|
|
}
|
|
if (value.toLowerCase().indexOf('rgb') < 0) {
|
|
return value;
|
|
}
|
|
value = value.replace(/^rgb\(/i, '').replace(/\)$/, '');
|
|
value_list = value.split(',');
|
|
|
|
var hex = '';
|
|
for (var i = 0; i < value_list.length; i++) {
|
|
var color = parseInt(String(value_list[i]).trim(), 10).toString(16);
|
|
if (color.length == 1) {
|
|
color = '0' + color;
|
|
}
|
|
hex += color;
|
|
}
|
|
return hex;
|
|
}
|
|
|
|
/**
|
|
* Send an email
|
|
*
|
|
* @deprecated
|
|
* @param string email_address
|
|
* @return void
|
|
*/
|
|
function sendMailTo(email_address) {
|
|
location.href = 'mailto:' + email_address;
|
|
}
|
|
|
|
/**
|
|
* View skin information
|
|
*
|
|
* @deprecated
|
|
* @param string module
|
|
* @param string skin
|
|
* @return void
|
|
*/
|
|
function viewSkinInfo(module, skin) {
|
|
const url = './?module=module&act=dispModuleSkinInfo&selected_module=' + module + '&skin=' + skin;
|
|
popopen(url, 'SkinInfo');
|
|
}
|
|
|
|
/**
|
|
* Sleep for seconds
|
|
*
|
|
* @deprecated
|
|
* @param float sec
|
|
* @return void
|
|
*/
|
|
function xSleep(sec) {
|
|
sec = sec / 1000;
|
|
var now = new Date();
|
|
var sleep = new Date();
|
|
while (sleep.getTime() - now.getTime() < sec) {
|
|
sleep = new Date();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if any argument is a defined variable
|
|
*
|
|
* @deprecated
|
|
* @param mixed arguments
|
|
* @return bool
|
|
*/
|
|
function isDef() {
|
|
for (let i = 0; i < arguments.length; ++i) {
|
|
if (typeof(arguments[i]) == 'undefined') {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check if a variable is defined and not null
|
|
*
|
|
* This seems to be similar to isset() in PHP
|
|
*
|
|
* @deprecated
|
|
* @param mixed v
|
|
* @return bool
|
|
*/
|
|
function is_def(v) {
|
|
return typeof(v) != 'undefined' && v !== null;
|
|
}
|
|
|
|
/**
|
|
* Convert the first character of a string to uppercase
|
|
*
|
|
* @deprecated
|
|
* @param string str
|
|
* @return string
|
|
*/
|
|
function ucfirst(str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
|
|
/**
|
|
* Get an element by ID
|
|
*
|
|
* @deprecated
|
|
* @param string id
|
|
* @return HTMLElement|null
|
|
*/
|
|
function get_by_id(id) {
|
|
return document.getElementById(id);
|
|
}
|
|
|
|
/**
|
|
* Get the left position of an object
|
|
*
|
|
* @deprecated
|
|
* @param HTMLElement obj
|
|
* @return int
|
|
*/
|
|
function GetObjLeft(obj) {
|
|
return $(obj).offset().left;
|
|
}
|
|
|
|
/**
|
|
* Get the top position of an object
|
|
*
|
|
* @deprecated
|
|
* @param HTMLElement obj
|
|
* @return int
|
|
*/
|
|
function GetObjTop(obj) {
|
|
return $(obj).offset().top;
|
|
}
|
|
|
|
/**
|
|
* Get the outer HTML of an object
|
|
*
|
|
* @deprecated
|
|
* @param HTMLElement obj
|
|
* @return string
|
|
*/
|
|
function getOuterHTML(obj) {
|
|
return $(obj).html().trim();
|
|
}
|
|
|
|
/**
|
|
* Replace the entire object with the given HTML
|
|
*
|
|
* @deprecated
|
|
* @param HTMLElement obj
|
|
* @param string html
|
|
* @return void
|
|
*/
|
|
function replaceOuterHTML(obj, html) {
|
|
$(obj).replaceWith(html);
|
|
}
|
|
|
|
/**
|
|
* Show or hide an element
|
|
*
|
|
* @deprecated
|
|
* @param string id
|
|
* @return void
|
|
*/
|
|
function toggleDisplay(id) {
|
|
$('#' + id).toggle();
|
|
}
|
|
|
|
/**
|
|
* Toggle between HTTP and HTTPS
|
|
*
|
|
* @deprecated
|
|
* @return void
|
|
*/
|
|
function toggleSecuritySignIn() {
|
|
var href = location.href;
|
|
if (/https:\/\//i.test(href)) {
|
|
location.href = href.replace(/^https/i,'http');
|
|
} else {
|
|
location.href = href.replace(/^http/i,'https');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display a message and reload the page
|
|
*
|
|
* @deprecated
|
|
* @param object ret_obj
|
|
* @return void
|
|
*/
|
|
function completeMessage(ret_obj) {
|
|
alert(ret_obj.message);
|
|
location.reload();
|
|
}
|
|
|
|
/**
|
|
* Just reload the current page
|
|
*
|
|
* @deprecated
|
|
* @return void
|
|
*/
|
|
function reloadDocument() {
|
|
location.reload();
|
|
}
|
|
|
|
/**
|
|
* Open a calendar popup
|
|
*
|
|
* @deprecated
|
|
* @param string fo_id
|
|
* @param string day_str
|
|
* @param function callback_func
|
|
* @return void
|
|
*/
|
|
function open_calendar(fo_id, day_str, callback_func) {
|
|
console.warn('open_calendar() is a no-op in Rhymix');
|
|
}
|
|
|
|
/**
|
|
* Display a popup menu
|
|
*
|
|
* @deprecated
|
|
* @param object ret_obj
|
|
* @param object response_tags
|
|
* @param object params
|
|
* @return void
|
|
*/
|
|
function displayPopupMenu(ret_obj, response_tags, params) {
|
|
Rhymix.displayPopupMenu(ret_obj, response_tags, params);
|
|
}
|
|
|
|
/**
|
|
* Create a popup menu
|
|
*
|
|
* @deprecated
|
|
* @return void
|
|
*/
|
|
function createPopupMenu() {
|
|
console.warn('createPopupMenu() is a no-op in Rhymix');
|
|
}
|
|
|
|
/**
|
|
* Check (?) a popup menu
|
|
*
|
|
* @deprecated
|
|
* @return void
|
|
*/
|
|
function chkPopupMenu() {
|
|
console.warn('chkPopupMenu() is a no-op in Rhymix');
|
|
}
|
|
|
|
/**
|
|
* These functions were used in xpresseditor
|
|
*/
|
|
function zbxe_folder_open(id) {
|
|
$("#folder_open_" + id).hide();
|
|
$("#folder_close_" + id).show();
|
|
$("#folder_" + id).show();
|
|
}
|
|
function zbxe_folder_close(id) {
|
|
$("#folder_open_" + id).show();
|
|
$("#folder_close_" + id).hide();
|
|
$("#folder_" + id).hide();
|
|
}
|
|
function svc_folder_open(id) {
|
|
$("#_folder_open_" + id).hide();
|
|
$("#_folder_close_" + id).show();
|
|
$("#_folder_" + id).show();
|
|
}
|
|
function svc_folder_close(id) {
|
|
$("#_folder_open_" + id).show();
|
|
$("#_folder_close_" + id).hide();
|
|
$("#_folder_" + id).hide();
|
|
}
|
|
|
|
/**
|
|
* Shims for old variable names and functions
|
|
*/
|
|
var loaded_popup_menus = Rhymix.loadedPopupMenus;
|
|
var objectExtend = $.extend;
|
|
var ssl_actions = [];
|
|
if (typeof(resizeImageContents) == 'undefined') {
|
|
window.resizeImageContents = function() {};
|
|
}
|
|
if (typeof(activateOptionDisabled) == 'undefined') {
|
|
window.activateOptionDisabled = function() {};
|
|
}
|
|
|
|
/**
|
|
* Shim for Modernizr if it is not loaded
|
|
*/
|
|
if (!window.Modernizr) {
|
|
window.Modernizr = {
|
|
audio: true,
|
|
video: true,
|
|
canvas: true,
|
|
history: true,
|
|
postmessage: true,
|
|
geolocation: ('geolocation' in navigator),
|
|
touch: ('ontouchstart' in window) || (navigator.maxTouchPoints > 0),
|
|
webgl: !!window.WebGLRenderingContext
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Shim for base64 encoding and decoding
|
|
*
|
|
* http://www.webtoolkit.info/
|
|
*/
|
|
const Base64 = {
|
|
|
|
// private property
|
|
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
|
|
|
// public method for encoding
|
|
encode : function (input) {
|
|
var output = "";
|
|
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
|
var i = 0;
|
|
|
|
input = Base64._utf8_encode(input);
|
|
|
|
while (i < input.length) {
|
|
|
|
chr1 = input.charCodeAt(i++);
|
|
chr2 = input.charCodeAt(i++);
|
|
chr3 = input.charCodeAt(i++);
|
|
|
|
enc1 = chr1 >> 2;
|
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
|
enc4 = chr3 & 63;
|
|
|
|
if (isNaN(chr2)) {
|
|
enc3 = enc4 = 64;
|
|
} else if (isNaN(chr3)) {
|
|
enc4 = 64;
|
|
}
|
|
|
|
output = output +
|
|
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
|
|
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
|
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
// public method for decoding
|
|
decode : function (input) {
|
|
var output = "";
|
|
var chr1, chr2, chr3;
|
|
var enc1, enc2, enc3, enc4;
|
|
var i = 0;
|
|
|
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
|
|
|
while (i < input.length) {
|
|
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
|
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
|
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
|
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
|
|
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
|
|
|
output = output + String.fromCharCode(chr1);
|
|
|
|
if (enc3 != 64) {
|
|
output = output + String.fromCharCode(chr2);
|
|
}
|
|
if (enc4 != 64) {
|
|
output = output + String.fromCharCode(chr3);
|
|
}
|
|
}
|
|
|
|
output = Base64._utf8_decode(output);
|
|
|
|
return output;
|
|
|
|
},
|
|
|
|
// private method for UTF-8 encoding
|
|
_utf8_encode : function (string) {
|
|
string = string.replace(/\r\n/g,"\n");
|
|
var utftext = "";
|
|
|
|
for (var n = 0; n < string.length; n++) {
|
|
var c = string.charCodeAt(n);
|
|
|
|
if (c < 128) {
|
|
utftext += String.fromCharCode(c);
|
|
}
|
|
else if((c > 127) && (c < 2048)) {
|
|
utftext += String.fromCharCode((c >> 6) | 192);
|
|
utftext += String.fromCharCode((c & 63) | 128);
|
|
}
|
|
else {
|
|
utftext += String.fromCharCode((c >> 12) | 224);
|
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
|
utftext += String.fromCharCode((c & 63) | 128);
|
|
}
|
|
}
|
|
|
|
return utftext;
|
|
},
|
|
|
|
// private method for UTF-8 decoding
|
|
_utf8_decode : function (utftext) {
|
|
var string = "";
|
|
var i = 0;
|
|
var c = 0, c1 = 0, c2 = 0, c3 = 0;
|
|
|
|
while ( i < utftext.length ) {
|
|
c = utftext.charCodeAt(i);
|
|
|
|
if (c < 128) {
|
|
string += String.fromCharCode(c);
|
|
i++;
|
|
}
|
|
else if((c > 191) && (c < 224)) {
|
|
c2 = utftext.charCodeAt(i+1);
|
|
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
|
i += 2;
|
|
}
|
|
else {
|
|
c2 = utftext.charCodeAt(i+1);
|
|
c3 = utftext.charCodeAt(i+2);
|
|
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
|
i += 3;
|
|
}
|
|
}
|
|
|
|
return string;
|
|
}
|
|
};
|