/*
* Project Name : Visual Python
* Description : GUI-based Python code generator
* File Name : com_util.js
* Author : Black Logic
* Note : Common utility function
* License : GPLv3 (GNU General Public License v3.0)
* Date : 2021. 08. 14
* Change Date :
*/
//============================================================================
// Common utility function
//============================================================================
define([
'vp_base/js/com/com_String'
], function (com_String) {
'use strict'
//========================================================================
// Define variable
//========================================================================
let isAPIListRunCode = true;
//========================================================================
// Internal call function
//========================================================================
/**
* check duplicate variable name
* @param {string} varName
*/
var _checkVariableNameDuplicate = function(varName) {
// TODO: varName duplicate check
return true;
}
//========================================================================
// External call function
//========================================================================
/**
* Generate uuid
* @returns {String} uuid
*/
var getUUID = function() {
return 'u' + ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
/**
* append css on global
* @param {String} url style url
*/
var loadCss = function(url) {
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = require.toUrl(url);
document.getElementsByTagName('head')[0].appendChild(link);
}
/**
* VisualPython container selector (jquery selector)
* @returns vp top container selector
*/
var getVPContainer = function() {
return '#vp_wrapper';
}
/**
* wrap selector
* @param {String} selector selector
* @returns wraped selecotr
*/
var wrapSelector = function(selector = '') {
var sbSelector = new com_String();
var cnt = arguments.length;
// no more selector
if (cnt < 2) {
sbSelector.appendFormat('{0} {1}', getVPContainer(), selector);
} else {
sbSelector.appendFormat('{0}', getVPContainer());
for (var idx = 0; idx < cnt; idx++) {
sbSelector.appendFormat(' {0}', arguments[idx]);
}
}
return sbSelector.toString();
}
/**
* add variable and trigger event
* @param {string} varName variable name
* @param {string} varType variable type
* @returns if return 0 when success, -1 when variable name duplicate
*/
var addVariable = function(varName, varType) {
// varName check duplicate
if (_checkVariableNameDuplicate) {
return -1;
} else {
events.trigger('add-variable.vp-wrapper', {'varName': varName, 'varType': varType});
return 0;
}
}
/**
* format simple string
*/
var formatString = function() {
var cnt = arguments.length;
if (cnt < 2)
return arguments[0];
var str = arguments[0];
for (var idx = 1; idx < cnt; idx++)
str = str.replace('{' + (idx - 1) + '}', arguments[idx]);
return str;
}
/**
* Convert to string format if not numeric
* @param {*} code
* @returns
*/
var convertToStr = function(code, isText=null, useRegex=false) {
let prefix = '';
if (useRegex) {
prefix = 'r';
}
if (isText != null) {
if (isText) {
code = `${prefix}'${code}'`;
}
} else {
if (!$.isNumeric(code)) {
if (code.includes("'")) {
code = `${prefix}"${code}"`;
} else {
code = `${prefix}'${code}'`;
}
}
}
return code;
}
/**
* Remove head's script(css, js)
* @param {string} scriptName
*/
var removeHeadScript = function(scriptName) {
for (let i = 0; i < document.querySelector('head').children.length; i++){
if (document.querySelector('head') && document.querySelector('head').children[i].outerHTML.includes(scriptName)) {
document.querySelector('head').removeChild(document.querySelector('head').children[i]);
}
}
}
/**
* Modal
* @param {Object} config { title, message, buttons(list), final(function), defaultIdx(int) }
*/
var renderModal = function(config={title:'', message:'', buttons:['Ok']}) {
require(['vp_base/js/com/component/Modal'], function(Modal) {
let modal = new Modal(config);
modal.open();
});
}
/**
* InfoModal
* @param {string} titleStr
*/
var renderInfoModal = function(titleStr) {
require(['vp_base/js/com/component/InfoModal'], function(InfoModal) {
new InfoModal(titleStr);
});
}
/**
* AlertModal
* @param {string} titleStr
*/
var renderAlertModal = function(titleStr, detail='') {
require(['vp_base/js/com/component/AlertModal'], function(AlertModal) {
new AlertModal(titleStr, detail=detail);
});
}
/**
* Show success message on the top right of the screen
* @param {string} titleStr
*/
var renderSuccessMessage = function(titleStr) {
require(['vp_base/js/com/component/SuccessMessage'], function(SuccessMessage) {
new SuccessMessage(titleStr);
});
}
/**
* Template for error box
* @param {*} titleStr
* @param {*} contentStr
* @returns
*/
var templateForErrorBox = function(titleStr, contentStr='', detailStr='') {
let errorContent = new com_String();
errorContent.appendFormatLine('
', 'vp-data-error-box', (detailStr && detailStr.length > 0)?('title="'+detailStr+"'"):'');
errorContent.appendLine('
');
errorContent.appendFormatLine('
',
'vp-data-error-box-title', titleStr);
if (contentStr && contentStr != '') {
errorContent.appendFormatLine('
{0}', contentStr.split('\\n').join('
'));
}
errorContent.appendLine('
');
return errorContent.toString();
}
/**
* setIsAPIListRunCode
*/
var setIsAPIListRunCode = function(isAPIListRunCode_param) {
isAPIListRunCode = isAPIListRunCode_param;
}
/**
* getIsAPIListRunCode
*/
var getIsAPIListRunCode = function() {
return isAPIListRunCode;
}
/**
* Convert string(include html text) to safe string to display
* @param {String} text
* @returns
*/
var safeString = function(text) {
return String(text).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
}
var optionToLabel = function(label) {
label = label.replaceAll('_', ' ');
label = label.charAt(0).toUpperCase() + label.slice(1);
return label;
}
/**
* Pack the code with ignoring the warnings
* @param {*} code
*/
var ignoreWarning = function(code) {
var convertedCode = new com_String();
convertedCode.appendLine('import warnings');
convertedCode.appendLine('from IPython.display import display');
convertedCode.appendLine('with warnings.catch_warnings():');
convertedCode.appendLine(" warnings.simplefilter('ignore')");
let codeLines = code.split('\n');
codeLines.forEach((line, idx) => {
if (idx > 0) {
convertedCode.appendLine();
}
if (codeLines.length == idx + 1) {
// last line
convertedCode.appendFormat(" display({0})", line);
} else {
convertedCode.appendFormat(" {0}", line);
}
});
return convertedCode.toString();
}
//============================================================================
// Cross-browser RegEx Split
//============================================================================
// This code has been MODIFIED from the code licensed below to not replace the
// default browser split. The license is reproduced here.
// see http://blog.stevenlevithan.com/archives/cross-browser-split for more info:
/*!
* Cross-Browser Split 1.1.1
* Copyright 2007-2012 Steven Levithan
* Available under the MIT License
* ECMAScript compliant, uniform cross-browser split method
*/
/**
* Splits a string into an array of strings using a regex or string
* separator. Matches of the separator are not included in the result array.
* However, if `separator` is a regex that contains capturing groups,
* backreferences are spliced into the result each time `separator` is
* matched. Fixes browser bugs compared to the native
* `String.prototype.split` and can be used reliably cross-browser.
* @param {String} str String to split.
* @param {RegExp} separator Regex to use for separating
* the string.
* @param {Number} [limit] Maximum number of items to include in the result
* array.
* @returns {Array} Array of substrings.
* @example
*
* // Basic use
* regex_split('a b c d', ' ');
* // -> ['a', 'b', 'c', 'd']
*
* // With limit
* regex_split('a b c d', ' ', 2);
* // -> ['a', 'b']
*
* // Backreferences in result array
* regex_split('..word1 word2..', /([a-z]+)(\d+)/i);
* // -> ['..', 'word', '1', ' ', 'word', '2', '..']
*/
var regex_split = function (str, separator, limit) {
var output = [],
flags = (separator.ignoreCase ? "i" : "") +
(separator.multiline ? "m" : "") +
(separator.extended ? "x" : "") + // Proposed for ES6
(separator.sticky ? "y" : ""), // Firefox 3+
lastLastIndex = 0,
separator2, match, lastIndex, lastLength;
// Make `global` and avoid `lastIndex` issues by working with a copy
separator = new RegExp(separator.source, flags + "g");
var compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined";
if (!compliantExecNpcg) {
// Doesn't need flags gy, but they don't hurt
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
}
/* Values for `limit`, per the spec:
* If undefined: 4294967295 // Math.pow(2, 32) - 1
* If 0, Infinity, or NaN: 0
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
* If other: Type-convert, then use the above rules
*/
limit = typeof(limit) === "undefined" ?
-1 >>> 0 : // Math.pow(2, 32) - 1
limit >>> 0; // ToUint32(limit)
for (match = separator.exec(str); match; match = separator.exec(str)) {
// `separator.lastIndex` is not reliable cross-browser
lastIndex = match.index + match[0].length;
if (lastIndex > lastLastIndex) {
output.push(str.slice(lastLastIndex, match.index));
// Fix browsers whose `exec` methods don't consistently return `undefined` for
// nonparticipating capturing groups
if (!compliantExecNpcg && match.length > 1) {
match[0].replace(separator2, function () {
for (var i = 1; i < arguments.length - 2; i++) {
if (typeof(arguments[i]) === "undefined") {
match[i] = undefined;
}
}
});
}
if (match.length > 1 && match.index < str.length) {
Array.prototype.push.apply(output, match.slice(1));
}
lastLength = match[0].length;
lastLastIndex = lastIndex;
if (output.length >= limit) {
break;
}
}
if (separator.lastIndex === match.index) {
separator.lastIndex++; // Avoid an infinite loop
}
}
if (lastLastIndex === str.length) {
if (lastLength || !separator.test("")) {
output.push("");
}
} else {
output.push(str.slice(lastLastIndex));
}
return output.length > limit ? output.slice(0, limit) : output;
};
//============================================================================
// End contributed Cross-browser RegEx Split
//============================================================================
return {
getUUID: getUUID,
loadCss: loadCss,
getVPContainer: getVPContainer,
wrapSelector: wrapSelector,
addVariable: addVariable,
formatString: formatString,
convertToStr: convertToStr,
optionToLabel: optionToLabel,
removeHeadScript: removeHeadScript,
renderModal: renderModal,
renderInfoModal: renderInfoModal,
renderAlertModal: renderAlertModal,
renderSuccessMessage: renderSuccessMessage,
templateForErrorBox: templateForErrorBox,
setIsAPIListRunCode: setIsAPIListRunCode,
getIsAPIListRunCode: getIsAPIListRunCode,
safeString: safeString,
ignoreWarning: ignoreWarning,
regex_split: regex_split
}
}); /* function, define */
/* End of file */