diff --git a/README.md b/README.md index 3f49817..5e5d08c 100644 --- a/README.md +++ b/README.md @@ -99,4 +99,9 @@ processMassiveImport | Process/Calculate the massive data | function | void Event | Description --- | --- -after.mp.process | This event fires when the procedure/calculation is done \ No newline at end of file +after.mp.process | This event fires when the procedure/calculation is done + +## Support + +If you're having any issue by using Massimp, contact me through the following e-mail address: +**[renan_ncs@msn.com](mailto:renan_ncs@msn.com)** \ No newline at end of file diff --git a/dist/css/massimp.css b/dist/css/massimp.css new file mode 100644 index 0000000..277fd18 --- /dev/null +++ b/dist/css/massimp.css @@ -0,0 +1,62 @@ +/** + Massimp - v0.1 + https://github.com/Niemietz/massimp + + Written in JavaScript (ES6) + Created by Renan Niemietz Cardoso +*/ + +.massimp-container .massimp-table-group +{ + overflow-y: auto; +} + +.massimp-img-thumbnail +{ + padding: .25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: .25rem; + max-width: 100%; + height: auto; +} + +.thumbnail { + max-width: 40%; +} + +.italic { font-style: italic; } +.small { font-size: 0.8em; } + +/** LIGHTBOX MARKUP **/ + +.lightbox { + /** Default lightbox to hidden */ + display: none; + + /** Position and style */ + position: fixed; + z-index: 999; + width: 100%; + height: 100%; + text-align: center; + top: 0; + left: 0; + background: rgba(0,0,0,0.8); + cursor: default; +} + +.lightbox img { + /** Pad the lightbox image */ + max-width: 90%; + max-height: 80%; + margin-top: 2%; +} + +.lightbox:target { + /** Remove default browser outline */ + outline: none; + + /** Unhide lightbox **/ + display: block; +} \ No newline at end of file diff --git a/dist/css/massimp.min.css b/dist/css/massimp.min.css new file mode 100644 index 0000000..b3e4b1d --- /dev/null +++ b/dist/css/massimp.min.css @@ -0,0 +1 @@ +.massimp-container .massimp-table-group{overflow-y:auto}.massimp-img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.thumbnail{max-width:40%}.italic{font-style:italic}.small{font-size:.8em}.lightbox{display:none;position:fixed;z-index:999;width:100%;height:100%;text-align:center;top:0;left:0;background:rgba(0,0,0,.8);cursor:default}.lightbox img{max-width:90%;max-height:80%;margin-top:2%}.lightbox:target{outline:none;display:block} \ No newline at end of file diff --git a/dist/js/massimp.js b/dist/js/massimp.js new file mode 100644 index 0000000..18c0a69 --- /dev/null +++ b/dist/js/massimp.js @@ -0,0 +1,2422 @@ +/** + Massimp - v0.1 + https://github.com/Niemietz/massimp + + Written in JavaScript (ES6) + Created by Renan Niemietz Cardoso +*/ + +const Massimp = (function () +{ + // ===== "GLOBAL" VARIABLES AND CONSTANTS ===== + let atributos = [ ]; + + const massimpErrorPrefix = "Massimp Error: "; + const _languages = { + "en-us": { + // MASSIMP ERRORs + elementNotFound: massimpErrorPrefix + "Element not found", + fileWithNoContent: massimpErrorPrefix + "File without content", + invalidFile: massimpErrorPrefix + "Invalid file", + noDataProcessed: massimpErrorPrefix + "No data was processed", + noAttributeAssociated: massimpErrorPrefix + "None attribute was associated to any column from file", + noFileSet: massimpErrorPrefix + "No file was set", + + // ELEMENTs STRINGs + list: "List", + fileChoose: "Choose a file", + fileWithHeader: "Header (It has a column title at the 1st line)", + fileWithoutHeader: "No Header (It doesn't have a column title at the 1st line)", + defaultButtonText: "Do it!", + extraButtonText: "Cancel", + line: "Line", + column: "Column", + attribute: "Attribute", + open: "Open", + close: "Close", + change: "Change", + remove: "Remove", + }, + "pt-br": { + // MASSIMP ERRORs + elementNotFound: massimpErrorPrefix + "Elemento não encontrado", + fileWithNoContent: massimpErrorPrefix + "Não foi possível encontrar conteúdo neste arquivo!", + invalidFile: massimpErrorPrefix + "Arquivo inválido", + noDataProcessed: massimpErrorPrefix + "Nenhum dado foi processado", + noAttributeAssociated: massimpErrorPrefix + "Nenhum atributo foi associado à nenhuma coluna do arquivo", + noFileSet: massimpErrorPrefix + "Nenhum arquivo foi selecionado", + + // ELEMENTs STRINGs + list: "Lista", + fileChoose: "Escolha um arquivo", + fileWithHeader: "Com cabeçalho (Com o título da coluna na 1ª linha)", + fileWithoutHeader: "Sem cabeçalho (Sem o título da coluna na 1ª linha)", + defaultButtonText: "Processar!", + extraButtonText: "Cancelar", + line: "Linha", + column: "Coluna", + attribute: "Atributo", + open: "Abrir", + close: "Fechar", + change: "Alterar", + remove: "Remover", + }, + }; + + Object.keys(_languages).forEach(function(key) + { + const lang = _languages[key]; + lang["languageNotSupported"] = "Massimp Error: Unsupported language"; + }); + + let _selectedLanguage = navigator.language.toLocaleLowerCase() || navigator.userLanguage.toLocaleLowerCase(); + + if(_selectedLanguage == null || !Object.keys(_languages).includes(_selectedLanguage)) + { + console.warn("Massimp Warning: Could not use local language, setting English (en-US) as default language."); + _selectedLanguage = "en-us"; + } + + let _sheets = null; + let _sheetIndex = 0; + let _header = true; + let _showImagesTable = false; + let _imagesProcessed = true; + + // ELEMENT CLASSES OR/AND IDs + const inputGroupElementClass = "massimp-file-group"; + const customFileElementClass = "massimp-custom-file"; + const inputFileInsideTextGroupElementClass = "massimp-file-group-append"; + const clearInputFileGroupElementClass = "massimp-file-group-clean"; + const radioGroupElementClass = "massimp-radio-group"; + const radioElementClass = "massimp-radio"; + const radioHasHeaderElementName = "massimp-has-header"; + + const sheetsRadioGroupElementClass = "massimp-excel-sheets"; + const radioSheetElementName = "massimp-sheet"; + + const tableDivElementClass = "massimp-table-group"; + const tableElementTag = "table"; + const tableBodyElementTag = "tbody"; + const tableHeadElementTag = "thead"; + + const tableResultDivElementClass = "massimp-table-result-group"; + + const buttonsGroupElementClass = "massimp-buttons-group"; + const defaultButtonElementClass = "massimp-default-button"; + const extraButtonElementClass = "massimp-extra-button"; + + // ===== PRIVATE "GLOBAL" FUNCTIONS ===== + /** excelFileToJSON + * @param fileBinary + * @param {Boolean} hasHeader - If spreadsheet has the column names on the first line + */ + function excelFileToJSON(fileBinary, hasHeader = true) + { + const workbook = XLSX.read(fileBinary, { + type: 'binary' + }); + + const sheets = []; + + workbook.SheetNames.forEach((sheetName) => + { + let options = { }; + if(!hasHeader) + { + options["header"] = 1; + } + + // XLSX sheet rows converted into array + const rowsArray = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName], options); + + const sheet = { "nome": sheetName, "conteudo": rowsArray }; + + sheets.push(sheet); + }); + + return sheets; + }; + + /** excelFileInputToJSON + * @param {HTMLElement} fileInput - Spreadsheet file input element + * @param {Function} success - Action after parsing + * @param {Function} error - Action if error on parsing + * @param {Boolean} hasHeader - If spreadsheet has the column names on the first line + */ + function excelFileInputToJSON(fileInput, success, error, hasHeader = true) + { + const fileReader = new FileReader(); + + fileReader.onload = (e) => + { + try + { + const fileBin = e.target.result; + + const excelSheets = excelFileToJSON(fileBin, hasHeader); + + success(excelSheets); + } + catch(ex) + { + error(ex); + } + }; + + fileReader.onerror = (ex) => + { + error(ex); + }; + + fileReader.readAsBinaryString(fileInput.files[0]); + }; + + /** renameObjectKeys + * @param {JSON} object - Object in which keys will be renamed + * @param {Array} array_FromTo - Array of objects that has to follow the following format: [{ "from": string, "to": string }] */ + function renameObjectKeys(object, array_FromTo) + { + let result = Object.assign({}, object); + + array_FromTo.forEach(function(item, index) + { + const from = item.from; + const to = item.to; + + if(result[from] != null) + { + result[to] = result[from]; + delete result[from]; + } + }); + + return result; + }; + + /** getAllIndexes + * @param {Array} arr - Array to be looked for + * @param val - Value to look for in array + * @param attr - Attribute to search in array objects */ + function getAllIndexes(arr, val, attr = null) + { + let indexes = [], i; + for(i = 0; i < arr.length; i++) + { + if(attr != null) + { + if (arr[i][attr] === val) + { + indexes.push(i); + } + } + else + { + if (arr[i] === val) + { + indexes.push(i); + } + } + } + return indexes; + } + + const privateProps = new WeakMap(); + + /** Massimp + * @param _element + * @param {Object} _options + */ + class Massimp + { + constructor(_element, _options) + { + if(typeof _element === "string") + { + _element = document.querySelector(_element); + _element._massimp = this; + } + + privateProps.set(this, { + element: _element, + options: _options, + + // ===== PRIVATE FUNCTIONS ===== + + _getStringList: function() + { + return _languages[_selectedLanguage.toLocaleLowerCase()]; + }, + + // CREATING AND LOADING MASSIMP CONTAINER HTML + _loadHTML: function() + { + /* +
+ +
+ */ + + let radPlanilha = document.createElement('input'); + radPlanilha.setAttribute('type', 'radio'); + radPlanilha.id = 'massimp-sheet-' + index.toString(); + radPlanilha.setAttribute('name', 'massimp-sheet'); + radPlanilha.setAttribute('value', index.toString()); + radPlanilha.classList.add("with-gap"); + if(index == 0) + { + radPlanilha.setAttribute("checked", true); + } + radPlanilha.onchange = onSheetSelect; + + let label = document.createElement('span'); + label.innerHTML = planilha.nome; + + let radio = document.createElement('label'); + radio.classList.add("massimp-radio"); + + radio.appendChild(radPlanilha); + radio.appendChild(label); + + let radioRow = document.createElement('p'); + radioRow.appendChild(radio); + + radioSheets.appendChild(radioRow); + }); + + radioSheets.style.display = null; + }, + + _removeSheetSelection: function() + { + const radioSheets = this._getSheetsRadioElements(); + if(radioSheets != null) + { + while (radioSheets.firstChild) + { + radioSheets.removeChild(radioSheets.firstChild); + } + + radioSheets.style.display = "none"; + } + }, + + /** @_showResultTable + * @param {Array} result - Result of process and calculation + */ + _showResultTable: function(result) + { + let tableDiv = this._getTableResultDivElement(); + let tableBody = this._getTableResultBodyElement(); + let tableHead = this._getTableResultHeadElement(); + if(tableDiv != null && tableBody != null && tableHead != null && atributos.length > 0) + { + this._removeResultTable(); + + result.forEach((item, jndex) => + { + if(jndex == 0) + { + let headRow = document.createElement('tr'); + + Object.keys(atributos).forEach(function(key, index) + { + // HEAD + if(((atributos[key].isImage == null || atributos[key].isImage == false) && item[atributos[key].valor] != null) || atributos[key].isImage == true) + { + const indexHeadCol = document.createElement('th'); + indexHeadCol.setAttribute("scope", "col"); + indexHeadCol.innerHTML = atributos[key].titulo; + if(atributos[key].isImage == true) + { + indexHeadCol.style.textAlign = "center"; + } + headRow.appendChild(indexHeadCol); + } + }); + + tableHead.appendChild(headRow); + } + + // BODY + let row = document.createElement('tr'); + + let i = 0; + Object.keys(atributos).forEach((key, index) => + { + if(((atributos[key].isImage == null || atributos[key].isImage == false) && item[atributos[key].valor] != null) || atributos[key].isImage == true) + { + const attributeCol = document.createElement('td'); + attributeCol.classList.add("massimp-attribute-" + atributos[key].valor); + + let attributeContent = document.createElement('span'); + if(atributos[key].isImage == true) + { + attributeCol.style.textAlign = "center"; + + const anchor = document.createElement('a'); + anchor.setAttribute("href", "javascript:void(0);"); + anchor.classList.add("lightbox"); + anchor.id = "lightbox-" + jndex.toString() + "-" + i.toString(); + + const anchorImage = document.createElement('img'); + anchorImage.id = "massimp-anchorimg-" + jndex.toString() + "-" + i.toString(); + + const closeImage = document.createElement('span'); + closeImage.style.cursor = "pointer"; + closeImage.style.color = "white"; + closeImage.style.position = "absolute"; + closeImage.style.right = "20px"; + closeImage.style.top = "20px"; + //closeImage.style.fontSize = "xx-large"; + closeImage.style.fontSize = "70px"; + closeImage.setAttribute("title", this._getStringList().close); + //closeImage.innerHTML = "✕"; + //closeImage.innerHTML = "✗"; + closeImage.innerHTML = "✘"; + closeImage.onclick = function() + { + location.href = "#_"; + } + + anchor.appendChild(closeImage); + anchor.appendChild(anchorImage); + + const attributeImage = document.createElement('img'); + attributeImage.id = "massimp-image-" + jndex.toString() + "-" + i.toString(); + attributeImage.style.display = "none"; + attributeImage.style.objectFit = "contain"; + attributeImage.style.width = "65px"; + attributeImage.style.cursor = "pointer"; + attributeImage.classList.add("responsive-img"); + attributeImage.classList.add("massimp-img-thumbnail"); + attributeImage.onclick = function() + { + const anchorId = "lightbox" + this.id.substr(13, this.id.length); + + location.href = "#" + anchorId; + } + + const attributeInput = document.createElement('input'); + const attributeContent = document.createElement('button'); + const attributeCleanContent = document.createElement('button'); + + attributeInput.setAttribute("type", "file"); + attributeInput.setAttribute("accept", "image/*"); + attributeInput.style.display = "none"; + attributeInput.id = "massimp-input-" + jndex.toString() + "-" + i.toString(); + attributeInput.onchange = (e) => + { + const anchorimgId = attributeInput.id.substr(0, 8) + "anchorimg" + attributeInput.id.substr(13, attributeInput.id.length); + const anchorimg = document.getElementById(anchorimgId); + + const imageId = attributeInput.id.substr(0, 8) + "image" + attributeInput.id.substr(13, attributeInput.id.length); + const image = document.getElementById(imageId); + + const buttonId = attributeInput.id.substr(0, 8) + "button" + attributeInput.id.substr(13, attributeInput.id.length); + const button = document.getElementById(buttonId); + + const clearButtonId = attributeInput.id.substr(0, 8) + "clear-button" + attributeInput.id.substr(13, attributeInput.id.length); + const clearButton = document.getElementById(clearButtonId); + + if(attributeInput.files.length > 0) + { + const reader = new FileReader(); + + reader.onload = (evt) => + { + //button.innerHTML = this.files[0].name; + button.innerHTML = this._getStringList().change; + image.setAttribute('src', evt.target.result); + image.setAttribute('title', attributeInput.files[0].name); + anchorimg.setAttribute('src', evt.target.result); + } + reader.readAsDataURL(attributeInput.files[0]); + + image.style.display = null; + + clearButton.style.display = null; + } + else + { + button.innerHTML = this._getStringList().open; + image.removeAttribute('src'); + image.style.display = "none"; + + clearButton.style.display = "none"; + } + } + + attributeContent.setAttribute("type", "button"); + attributeContent.classList.add("btn"); + attributeContent.id = "massimp-button-" + jndex.toString() + "-" + i.toString(); + attributeContent.innerHTML = this._getStringList().open; + attributeContent.onclick = function() + { + const inputId = this.id.substr(0, 8) + "input" + this.id.substr(14, this.id.length); + const input = document.getElementById(inputId); + + input.click(); + } + + attributeCleanContent.setAttribute("type", "button"); + attributeCleanContent.setAttribute("title", this._getStringList().remove); + attributeCleanContent.classList.add("btn-flat"); + attributeCleanContent.classList.add("red-text"); + attributeCleanContent.id = "massimp-clear-button-" + jndex.toString() + "-" + i.toString(); + attributeCleanContent.innerHTML = "✖"; + attributeCleanContent.style.display = "none"; + attributeCleanContent.onclick = () => + { + const inputId = attributeCleanContent.id.substr(0, 8) + "input" + attributeCleanContent.id.substr(20, attributeCleanContent.id.length); + const input = document.getElementById(inputId); + + const imageId = attributeCleanContent.id.substr(0, 8) + "image" + attributeCleanContent.id.substr(20, attributeCleanContent.id.length); + const image = document.getElementById(imageId); + + const buttonId = attributeCleanContent.id.substr(0, 8) + "button" + attributeCleanContent.id.substr(20, attributeCleanContent.id.length); + const button = document.getElementById(buttonId); + + // REMOVING CHOSEN FILE + const parent = input.parentNode; + + document.tempForm = document.createElement("form"); + document.tempForm.appendChild(input); + document.tempForm.reset(); + + parent.appendChild(document.tempForm.childNodes[0]); + // -------------------- + + image.removeAttribute("src"); + image.style.display = "none"; + + button.innerHTML = this._getStringList().open; + + attributeCleanContent.style.display = "none"; + } + + attributeCol.appendChild(anchor); + attributeCol.appendChild(attributeImage); + attributeCol.appendChild(document.createElement("br")); + attributeCol.appendChild(attributeInput); + attributeCol.appendChild(attributeContent); + attributeCol.appendChild(document.createElement("br")); + attributeCol.appendChild(attributeCleanContent); + } + else + { + attributeContent.innerHTML = item[atributos[key].valor]; + attributeCol.appendChild(attributeContent); + } + + row.appendChild(attributeCol); + + i++; + } + }); + + tableBody.appendChild(row); + }); + + tableDiv.style.display = null; + + _showImagesTable = false; + } + }, + + /** @_removeResultTable */ + _removeResultTable: function() + { + let tableDiv = this._getTableResultDivElement(); + let tableBody = this._getTableResultBodyElement(); + let tableHead = this._getTableResultHeadElement(); + if(tableDiv != null && tableBody != null) + { + while (tableHead.firstChild) + { + tableHead.removeChild(tableHead.firstChild); + } + while (tableBody.firstChild) + { + tableBody.removeChild(tableBody.firstChild); + } + + tableDiv.style.display = "none"; + } + }, + + _processImages: function(ending = null) + { + this._process(false, (result) => + { + let tableResultBody = this._getTableResultBodyElement(); + if(tableResultBody != null) + { + result.forEach((item, index) => + { + const row = tableResultBody.childNodes[index]; + + row.querySelectorAll("td").forEach(function(col, colIndex) + { + // GETTING IMAGE ATTRIBUTE NAMES + const newClassList = Array.from(col.classList).filter(function(class_, classIndex) + { + let ok = true; + Object.keys(item).forEach(function(key, index) + { + if(class_.substr(18, class_.length) == key) + { + ok = false; + + return false; + } + }); + + return ok; + }); + + // SETTINGS IMAGE ATTRIBUTES + newClassList.forEach(function(class_, index) + { + const input = row.getElementsByClassName(class_)[0].getElementsByTagName('input')[0]; + + if(input != null && input.files.length > 0) + { + item[class_.substr(18, class_.length)] = input.files[0]; + } + else + { + item[class_.substr(18, class_.length)] = null; + } + }) + }); + }); + } + + // VALIDATING ALL ATTRIBUTES + let ok = false; + result.forEach(function(obj, index) + { + Object.keys(obj).forEach(function(key, index) + { + if(obj[key] != null) + { + ok = true; + + return false; + } + }); + + if(ok) + { + return false; + } + }); + + if(ok && ending != null && typeof ending === "function") + { + _showImagesTable = true; + + this._removeResultTable(); + + ending(result); + } + else if(!ok) + { + throw this._getStringList().noDataProcessed; + } + }) + }, + + _process: function(validate = true, ending = null) + { + let inputFile = this._getInputFileElement(); + if(inputFile != null && inputFile.files.length > 0) + { + let result = []; + + let ok = false; + if(!validate) + { + ok = true; + } + + let tableBody = this._getTableBodyElement(); + if(tableBody != null) + { + // RENAME ALL XLSX RESULT OBJECT ATTRIBUTES + let array_FromTo = []; + NodeList.prototype.forEach = Array.prototype.forEach; + const rows = tableBody.childNodes; + rows.forEach(function(row, index) + { + const atributo = row.getElementsByClassName('massimp-attribute-col')[0].getElementsByTagName('select')[0].value; + if(atributo != 0) + { + if(!ok) + { + ok = true; + } + + let from_to = { "from": index, "to": atributo }; + if(_header) + { + const colunaExcel = row.getElementsByClassName("massimp-column-col")[0].getElementsByTagName('span')[0].innerHTML; + + from_to = { "from": colunaExcel, "to": atributo }; + } + + array_FromTo.push(from_to); + } + }); + + if(ok) + { + _sheets[_sheetIndex].conteudo.forEach((item, index) => + { + let new_item = renameObjectKeys(item, array_FromTo); + + // REMOVE UNSET ATTRIBUTES FROM XLSX RESULT OBJECT + Object.keys(new_item).forEach(function(key, index) + { + if(!array_FromTo.find(from_to => { return from_to.to == key })) + { + delete new_item[key]; + } + }); + + // ADDING UNSET ATTRIBUTES WITH NULL VALUE + atributos.forEach(function(attr, index) + { + if(attr.valor != null && new_item[attr.valor] == null && (attr.isImage == null || attr.isImage == false)) + { + new_item[attr.valor] = null; + } + }); + + result.push(new_item); + }); + } + } + + if(ok && ending != null && typeof ending === "function") + { + ending(result); + } + else if(!ok) + { + throw this._getStringList().noAttributeAssociated; + } + } + else + { + throw this._getStringList().noFileSet; + } + }, + + // ERROR TREATMENT + _onError: function(error) + { + if(this.options != null && this.options.onError != null && typeof this.options.onError === "function") + { + this.options.onError(error); + } + else + { + console.error(error); + } + }, + }); + + try + { + // ===== MASSIMP START ===== + privateProps.get(this)._loadHTML(); + + // LANGUAGE + if(_options != null && _options.language != null && typeof _options.language === "string") + { + if(Object.keys(_languages).includes(_options.language.toLowerCase())) + { + _selectedLanguage = _options.language; + } + else + { + // Send the unsupported language error to user then keep going + privateProps.get(this)._onError(privateProps.get(this)._getStringList().languageNotSupported); + + // TODO Uncomment if you want to interrupt the code because of this unsupported language set by user + //throw privateProps.get(this)._getStringList().languageNotSupported; + } + } + + // ATRIBUTTES + if(_options != null && _options.attributes != null && typeof _options.attributes === "object") + { + Object.keys(_options.attributes).forEach(function(key, index) + { + let useIndex = true; + if(typeof parseInt(key) === "NaN") + { + useIndex = false; + } + + let newAttribute = { valor: "", titulo: "", isImage: false }; + if(_options.attributes[((useIndex) ? index : key)].valor != null) + { + newAttribute.valor = _options.attributes[((useIndex) ? index : key)].valor; + } + if(_options.attributes[((useIndex) ? index : key)].titulo != null) + { + newAttribute.titulo = _options.attributes[((useIndex) ? index : key)].titulo; + } + if(_options.attributes[((useIndex) ? index : key)].isImage != null) + { + newAttribute.isImage = _options.attributes[((useIndex) ? index : key)].isImage; + } + + atributos.push(newAttribute); + }); + + // TODO Change the code below if Massimp should send an error instead of deleting the twin attribute + let attr2Exclude = []; + for(let index = 0; index < atributos.length; index++) + { + const allOcorrencies = getAllIndexes(atributos, atributos[index].valor, "valor"); + if(allOcorrencies.length > 1) + { + allOcorrencies.forEach(function(ocorrency, i) + { + if(i > 0) + { + if(!attr2Exclude.includes(ocorrency)) + { + attr2Exclude.push(ocorrency); + } + } + }); + } + } + + attr2Exclude.forEach(function(attrIndex, index) + { + delete atributos[attrIndex]; + }); + // ------------------------------------------------------------------------------------------------- + } + + // INPUT FILE + const clearInputFile = (inputFile) => + { + try + { + // REMOVING CHOSEN FILE + const parent = inputFile.parentNode; + + document.tempForm = document.createElement("form"); + document.tempForm.appendChild(inputFile); + document.tempForm.reset(); + + parent.appendChild(document.tempForm.childNodes[0]); + // -------------------- + + // REMOVING COLUMN ASSOCIATION TABLE AND RESULT (IMAGE ASSOCIATION) TABLE + privateProps.get(this)._removeResultTable(); + privateProps.get(this)._removeColumnAssociationTable(); + + // INDICATING THAT A FILE WAS UNSET + const inputFileInsideText = privateProps.get(this)._getInputFileInsideTextElement(); + if(inputFile != null) + { + inputFileInsideText.removeAttribute("readonly"); + inputFileInsideText.classList.remove("valid"); + inputFileInsideText.classList.remove("invalid"); + + inputFileInsideText.value = null; + } + + // HIDING THE CLEAR FILE BUTTON + const clearButtonGroup = privateProps.get(this)._getClearInputFileGroupElement(); + clearButtonGroup.style.display = "none"; + + // HIDING THE SHEET SELECTION + const radioSheets = privateProps.get(this)._getSheetsRadioElements(); + radioSheets.style.display = "none"; + + // ENABLING 'HAS HEADER' RADIOS + const radios = privateProps.get(this)._getRadioElements(); + radios.forEach(function(radio, index) + { + radio.removeAttribute("disabled"); + }); + + // HIDING DEFAULT BUTTON + const defaultButton = privateProps.get(this)._getDefaultButtonElement(); + defaultButton.style.display = "none"; + + const radioHasHeader = privateProps.get(this)._getRadioHasHeaderElement(); + const hasHeader = JSON.parse(radioHasHeader.value); + + // DEFAULTING THE "GLOBAL" VARIABLES + _sheets = null; + _sheetIndex = 0; + _header = hasHeader; + _showImagesTable = false; + _imagesProcessed = true; + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + let inputFileText = privateProps.get(this)._getStringList().list; + if(privateProps.get(this).options != null && privateProps.get(this).options.inputFileText != null && typeof privateProps.get(this).options.inputFileText === "string") + { + inputFileText = privateProps.get(this).options.inputFileText; + } + + let inputFileInsideText = privateProps.get(this)._getStringList().fileChoose; + if(_options != null && _options.inputFileInsideText != null && typeof _options.inputFileInsideText === "string") + { + inputFileInsideText = _options.inputFileInsideText; + } + + const customFileInput = privateProps.get(this)._getInputFileElement(); + customFileInput.onchange = () => + { + try + { + // IF A FILE WAS SET + if(customFileInput.files[0] != null) + { + // REMOVE COLUMN ASSOCIATION TABLE AND RESULT (IMAGE ASSOCIATION) TABLE FROM PREVIOUS FILES + privateProps.get(this)._removeColumnAssociationTable(); + privateProps.get(this)._removeResultTable(); + + // INDICATES THAT A FILE WAS SET + const inputFileInsideText = privateProps.get(this)._getInputFileInsideTextElement(); + inputFileInsideText.setAttribute("readonly", true); + inputFileInsideText.classList.remove("invalid"); + inputFileInsideText.classList.add("valid"); + + inputFileInsideText.value = customFileInput.files[0].name; + + // SHOW CLEAR FILE BUTTON + const clearButtonGroup = privateProps.get(this)._getClearInputFileGroupElement(); + clearButtonGroup.style.display = null; + + const radioHasHeader = privateProps.get(this)._getRadioHasHeaderElement(); + const hasHeader = JSON.parse(radioHasHeader.value); + + // PROCESS FILE AND AFTER THAT vv + privateProps.get(this)._processFile(customFileInput, hasHeader, (excelSheets) => + { + privateProps.get(this)._showColumnAssociationTable(hasHeader, 0); + + let maxVerticalRowsToDisplay = 5; + if(_options != null && _options.maxVerticalRowsToDisplay != null && typeof _options.maxVerticalRowsToDisplay === "number") + { + maxVerticalRowsToDisplay = _options.maxVerticalRowsToDisplay; + } + + this.setMaxVerticalRowsToDisplay(maxVerticalRowsToDisplay); + + if(excelSheets.length > 1) + { + // SHOW SHEET SELECTION AND WHAT TO DO WHEN SHEET IS SELECTED + privateProps.get(this)._showSheetSelection(excelSheets, () => + { + _sheetIndex = parseInt(radPlanilha.value); // Change "global" sheetIndex variable + + privateProps.get(this)._showColumnAssociationTable(hasHeader, sheetIndex); + + let maxVerticalRowsToDisplay = 5; + if(_options != null && _options.maxVerticalRowsToDisplay != null && typeof _options.maxVerticalRowsToDisplay === "number") + { + maxVerticalRowsToDisplay = _options.maxVerticalRowsToDisplay; + } + + this.setMaxVerticalRowsToDisplay(maxVerticalRowsToDisplay); + }); + } + + // DISABLE 'HAS HEADER' RADIOS + const radios = privateProps.get(this)._getRadioElements(); + radios.forEach(function(radio, index) + { + radio.setAttribute("disabled", true); + }); + + // SHOW DEFAULT BUTTON + const defaultButton = privateProps.get(this)._getDefaultButtonElement(); + defaultButton.style.display = null; + }); + + // DEFAULTING THE "GLOBAL" VARIABLES + _sheets = null; + _sheetIndex = 0; + _header = hasHeader; + _showImagesTable = false; + _imagesProcessed = true; + } + // IF NO FILE WAS SET + else + { + clearInputFile(customFileInput); + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + const clearInputTextButton = privateProps.get(this)._getClearInputFileElement(); + clearInputTextButton.onclick = () => + { + try + { + const customFileInput = privateProps.get(this)._getInputFileElement(); + clearInputFile(customFileInput); + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + this.setInputFileInsideText(inputFileInsideText); + this.setInputFileText(inputFileText); + + // TABLE + let maxVerticalRowsToDisplay = 5; + if(_options != null && _options.maxVerticalRowsToDisplay != null && typeof _options.maxVerticalRowsToDisplay === "number") + { + maxVerticalRowsToDisplay = _options.maxVerticalRowsToDisplay; + } + + this.setMaxVerticalRowsToDisplay(maxVerticalRowsToDisplay); + + // DEFAULT BUTTON + let colorButtonClass = "blue"; + if(_options != null && _options.colorButtonClass != null && typeof _options.colorButtonClass === "string") + { + colorButtonClass = _options.colorButtonClass; + } + + let buttonText = privateProps.get(this)._getStringList().defaultButtonText; + if(_options != null && _options.buttonText != null && typeof _options.buttonText === "string") + { + buttonText = _options.buttonText; + } + + let _onButtonClicked = () => + { + try + { + if(_showImagesTable) + { + privateProps.get(this)._process(false, (result) => + { + privateProps.get(this)._showResultTable(result); + + _imagesProcessed = false; + }); + } + else + { + if(_imagesProcessed) + { + privateProps.get(this)._process(true, null); + } + else + { + privateProps.get(this)._processImages(null); + } + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + if(_options != null && _options.onButtonClicked != null && typeof _options.onButtonClicked === "function") + { + _onButtonClicked = () => + { + try + { + if(_showImagesTable) + { + privateProps.get(this)._process(false, (result) => + { + privateProps.get(this)._showResultTable(result); + + _imagesProcessed = false; + }); + } + else + { + if(_imagesProcessed) + { + privateProps.get(this)._process(true, _options.onButtonClicked); + } + else + { + privateProps.get(this)._processImages(_options.onButtonClicked); + } + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + } + + this.setColorButtonClass(colorButtonClass); + this.setButtonText(buttonText); + const defaultButton = privateProps.get(this)._getDefaultButtonElement(); + defaultButton.onclick = _onButtonClicked; + defaultButton.style.display = "none"; + + // EXTRA BUTTON + let showExtraButton = false; + if(_options != null && _options.showExtraButton != null && typeof _options.showExtraButton === "boolean") + { + showExtraButton = _options.showExtraButton; + } + + this.setShowExtraButton(showExtraButton); + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + // ===== PUBLIC FUNCTIONS ===== + + // INPUT FILE + setInputFileText(inputFileText = privateProps.get(this)._getStringList().list) + { + try + { + const inputGroupText = privateProps.get(this)._getInputFileTextElement(); + if(inputFileText != null && typeof inputFileText === "string" && inputFileText.length > 0) + { + inputGroupText.innerHTML = inputFileText; + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + setInputFileInsideText(inputFileInsideText = privateProps.get(this)._getStringList().fileChoose) + { + try + { + const customFileLabel = privateProps.get(this)._getInputFileInsideTextElement(); + if(inputFileInsideText != null) + { + customFileLabel.placeHolder = inputFileInsideText; + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + // TABLE + setMaxVerticalRowsToDisplay(maxVerticalRowsToDisplay = 5, checkNumberOfRows = false) + { + try + { + let maxHeight = 446; // DEFAULT ROWS TO DISPLAY (5 ROWS) - 75px PER ROW AFTER FIRST | 127px FOR FIRST ROW | +19px AT THE END + + if(maxVerticalRowsToDisplay != null && typeof maxVerticalRowsToDisplay === "number") + { + const tbody = privateProps.get(this)._getTableBodyElement(); + const numberOfRows = tbody.getElementsByTagName("tr").length; + if(checkNumberOfRows && maxVerticalRowsToDisplay >= numberOfRows) + { + maxHeight = 127 + ((numberOfRows - 1) * 75); + } + else + { + maxHeight = 127 + ((maxVerticalRowsToDisplay - 1) * 75); + } + } + + const tableDiv = privateProps.get(this)._getTableDivElement(); + tableDiv.style.maxHeight = maxHeight.toString() + "px"; + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + getNumberOfObjects() + { + let result = 0. + try + { + if(_sheets != null) + { + result = _sheets[_sheetIndex].conteudo.length; + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + + return result; + } + + // DEFAULT BUTTON + setColorButtonClass(colorButtonClass = "blue") + { + try + { + const okButton = privateProps.get(this)._getDefaultButtonElement(); + if(colorButtonClass != null && typeof colorButtonClass === "string" && colorButtonClass.length > 0) + { + okButton.removeAttribute("class"); + okButton.classList.add("btn"); + okButton.classList.add("waves-effect"); + okButton.classList.add("waves-light"); + okButton.classList.add(defaultButtonElementClass); + okButton.classList.add(colorButtonClass); + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + setButtonText(buttonText = privateProps.get(this)._getStringList().defaultButtonText) + { + try + { + const okButton = privateProps.get(this)._getDefaultButtonElement(); + if(buttonText != null && typeof buttonText === "string" && buttonText.length > 0) + { + okButton.innerHTML = buttonText; + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + // EXTRA BUTTON + setColorExtraButtonClass(colorExtraButtonClass = "red") + { + try + { + const extraButton = privateProps.get(this)._getExtraButtonElement(); + if(colorExtraButtonClass != null && typeof colorExtraButtonClass === "string" && colorExtraButtonClass.length > 0) + { + extraButton.removeAttribute("class"); + extraButton.classList.add("btn"); + extraButton.classList.add("waves-effect"); + extraButton.classList.add("waves-light"); + extraButton.classList.add(extraButtonElementClass); + extraButton.classList.add(colorExtraButtonClass); + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + setExtraButtonText(extraButtonText = privateProps.get(this)._getStringList().extraButtonText) + { + try + { + const extraButton = privateProps.get(this)._getExtraButtonElement(); + if(extraButtonText != null && typeof extraButtonText === "string" && extraButtonText.length > 0) + { + extraButton.innerHTML = extraButtonText; + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + setShowExtraButton(showExtraButton = false) + { + try + { + const formGroup = privateProps.get(this)._getButtonsGroupElement(); + const extraButton = privateProps.get(this)._getExtraButtonElement(); + if(extraButton != null) + { + formGroup.removeChild(extraButton); + + if(showExtraButton) + { + const extraButton = document.createElement("button"); + extraButton.setAttribute("type", "button"); + extraButton.classList.add("btn"); + extraButton.classList.add("red"); + extraButton.classList.add("waves-effect"); + extraButton.classList.add("waves-light"); + extraButton.classList.add(extraButtonElementClass); + extraButton.innerHTML = privateProps.get(this)._getStringList().extraButtonText; + + formGroup.appendChild(extraButton); + + let colorExtraButtonClass = "red"; + if(privateProps.get(this).options != null && privateProps.get(this).options.colorExtraButtonClass != null && typeof privateProps.get(this).options.colorExtraButtonClass === "string") + { + colorExtraButtonClass = privateProps.get(this).options.colorExtraButtonClass; + } + let extraButtonText = privateProps.get(this)._getStringList().extraButtonText; + if(privateProps.get(this).options != null && privateProps.get(this).options.extraButtonText != null && typeof privateProps.get(this).options.extraButtonText === "string") + { + extraButtonText = privateProps.get(this).options.extraButtonText; + } + + let _onExtraButtonClicked = null; + if(privateProps.get(this).options != null && privateProps.get(this).options.onExtraButtonClicked != null && typeof privateProps.get(this).options.onExtraButtonClicked === "function") + { + _onExtraButtonClicked = privateProps.get(this).options.onExtraButtonClicked; + } + + privateProps.get(this)._setColorExtraButtonClass(colorExtraButtonClass); + privateProps.get(this)._setExtraButtonText(extraButtonText); + extraButton.onclick = _onExtraButtonClicked; + } + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + + processMassiveImport(ending = null) + { + try + { + if(_showImagesTable) + { + privateProps.get(this)._process(false, (result) => + { + privateProps.get(this)._showResultTable(result); + + _imagesProcessed = false; + }); + } + else + { + if(_imagesProcessed) + { + privateProps.get(this)._process(true, ending); + } + else + { + privateProps.get(this)._processImages(ending); + } + } + } + catch(ex) + { + privateProps.get(this)._onError(ex); + } + } + } + + return Massimp; +})(); + +/** baseMainFunction + * @param {Object} option - OPTIONS + * @param {String} method - METHOD + * @param argument1 - ARGUMENT A + * @param argument2 - ARGUMENT B + * @param argument3 - ARGUMENT C + */ +const massimpMainFunction = function(optionsOrMethod = {}, argument1 = null, argument2 = null, argument3 = null) +{ + let isUsingJquery = false; + + thisElement = this; + if(this[0] != null) + { + thisElement = this[0]; + isUsingJquery = true; + } + + // OPTIONS TREATMENT + if(typeof optionsOrMethod === "object") + { + if(thisElement._massimp == null) + { + thisElement._massimp = new Massimp(thisElement, optionsOrMethod); + } + } + + // METHODS AND EVENTS TREATMENT (jQuery Only) + else if(isUsingJquery && typeof optionsOrMethod === "string" && thisElement._massimp != null) + { + // METHODS + if(optionsOrMethod == "setInputFileText") + { + thisElement._massimp.setInputFileText(argument1); + } + else if(optionsOrMethod == "setInputFileInsideText") + { + thisElement._massimp.setInputFileInsideText(argument1); + } + else if(optionsOrMethod == "setMaxVerticalRowsToDisplay") + { + thisElement._massimp.setMaxVerticalRowsToDisplay(argument1); + } + else if(optionsOrMethod == "getNumberOfObjects") + { + return thisElement._massimp.getNumberOfObjects(); + } + else if(optionsOrMethod == "setColorButtonClass") + { + thisElement._massimp.setColorButtonClass(argument1); + } + else if(optionsOrMethod == "setButtonText") + { + thisElement._massimp.setButtonText(argument1); + } + else if(optionsOrMethod == "setColorExtraButtonClass") + { + thisElement._massimp.setColorExtraButtonClass(argument1); + } + else if(optionsOrMethod == "setExtraButtonText") + { + thisElement._massimp.setExtraButtonText(argument1); + } + else if(optionsOrMethod == "setShowExtraButton") + { + thisElement._massimp.setShowExtraButton(argument1); + } + + // METHODS W/ EVENT RELATED + else if(optionsOrMethod == "processMassiveImport") + { + thisElement._massimp.processMassiveImport(function(result) + { + $(thisElement).trigger("after.mp.process", [ result ] ); + }); + } + else + { + console.error("Massimp error: Method not found"); + } + } + else + { + console.error("Massimp error: Invalid initialization"); + } +}; + +if(window.jQuery != null) +{ + $.fn.massimp = massimpMainFunction; +} + +HTMLElement.prototype.massimp = massimpMainFunction; \ No newline at end of file diff --git a/dist/js/massimp.min.js b/dist/js/massimp.min.js new file mode 100644 index 0000000..48e48d6 --- /dev/null +++ b/dist/js/massimp.min.js @@ -0,0 +1,63 @@ +var Massimp=function(){function f(c,d){d=void 0===d?!0:d;var b=XLSX.read(c,{type:"binary"}),l=[];b.SheetNames.forEach(function(c){var e={};d||(e.header=1);e=XLSX.utils.sheet_to_row_object_array(b.Sheets[c],e);l.push({nome:c,conteudo:e})});return l}function r(c,d,b,l){l=void 0===l?!0:l;var e=new FileReader;e.onload=function(c){try{var e=f(c.target.result,l);d(e)}catch(D){b(D)}};e.onerror=function(c){b(c)};e.readAsBinaryString(c.files[0])}function x(c,b){var d=Object.assign({},c);b.forEach(function(c, + b){var e=c.from,l=c.to;null!=d[e]&&(d[l]=d[e],delete d[e])});return d}function G(c,d,b){b=void 0===b?null:b;var e=[],h;for(h=0;h