diff --git a/_cache_service_worker.js b/_cache_service_worker.js index cb38938..51b05fe 100644 --- a/_cache_service_worker.js +++ b/_cache_service_worker.js @@ -6,7 +6,7 @@ */ var PRECACHE_ID = 'rom-patcher-js'; -var PRECACHE_VERSION = 'v30rc1b'; +var PRECACHE_VERSION = 'v30rc2'; var PRECACHE_URLS = [ '/RomPatcher.js/', '/RomPatcher.js/index.html', '/RomPatcher.js/manifest.json', diff --git a/index.html b/index.html index 153938d..536a7f4 100644 --- a/index.html +++ b/index.html @@ -151,7 +151,7 @@ - Rom Patcher JS v3.0 RC1 by Marc Robledo + Rom Patcher JS v3.0 RC2 by Marc Robledo
See on GitHub Donate diff --git a/index_template.html b/index_template.html index eb308c6..66123e2 100644 --- a/index_template.html +++ b/index_template.html @@ -18,6 +18,7 @@ try { RomPatcherWeb.initialize({ language: 'en', //default: en + requireValidation: false }, { file: './my_patch.zip', //zip containing patches name: 'Game (English v1.0)', @@ -49,7 +50,7 @@ @@ -83,8 +84,7 @@
- +
diff --git a/rom-patcher-js/RomPatcher.webapp.js b/rom-patcher-js/RomPatcher.webapp.js index c55da1f..155ff98 100644 --- a/rom-patcher-js/RomPatcher.webapp.js +++ b/rom-patcher-js/RomPatcher.webapp.js @@ -59,9 +59,11 @@ var RomPatcherWeb = (function () { language: typeof navigator.language === 'string' ? navigator.language.substring(0, 2) : 'en', outputSuffix: true, fixChecksum: false, + requireValidation: false, allowDropFiles: false, + oninitialize: null, onloadrom: null, onvalidaterom: null, onloadpatch: null, @@ -71,7 +73,7 @@ var RomPatcherWeb = (function () { /* embeded patches */ - var embededPatchesInfo = null; + var currentEmbededPatches = null; const _parseEmbededPatchInfo = function (embededPatchInfo) { const parsedPatch = { file: embededPatchInfo.file.trim(), @@ -92,6 +94,8 @@ var RomPatcherWeb = (function () { parsedPatch.description = embededPatchInfo.description; } + parsedPatch.optional = !!embededPatchInfo.optional; + if (typeof embededPatchInfo.outputName === 'string') { parsedPatch.outputName = embededPatchInfo.outputName; } @@ -123,58 +127,68 @@ var RomPatcherWeb = (function () { return parsedPatch; } + var isFetching = false; const _fetchPatchFile = function (embededPatchInfo) { + if (isFetching) + throw new Error('Rom Patcher JS: already fetching another file'); + isFetching = true; + htmlElements.disableAll(); const spinnerHtml = ''; - - const loadingSpan = document.createElement('span'); - loadingSpan.id = 'rom-patcher-span-loading-embeded-patch'; - loadingSpan.innerHTML = _('Downloading...') + ' ' + spinnerHtml; - - const inputFilePatch = htmlElements.get('input-file-patch'); - if (inputFilePatch) { - inputFilePatch.parentElement.replaceChild(loadingSpan, inputFilePatch); - } else { - throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found'); - } + htmlElements.hide('select-patch'); + htmlElements.empty('select-patch'); + htmlElements.removeClass('select-patch', 'single'); + htmlElements.removeClass('select-patch', 'multiple'); + htmlElements.setEnabled('select-patch', false); + htmlElements.empty('container-optional-patches'); + htmlElements.setText('span-loading-embeded-patch', _('Downloading...') + ' ' + spinnerHtml); + htmlElements.show('span-loading-embeded-patch'); - - var uri = decodeURI(embededPatchInfo.file); - - fetch(uri) + fetch(decodeURI(embededPatchInfo.file)) .then(result => result.arrayBuffer()) // Gets the response and returns it as a blob .then(arrayBuffer => { const fetchedFile = new BinFile(arrayBuffer); if (ZIPManager.isZipFile(fetchedFile)) { if (typeof embededPatchInfo.patches === 'object') { if (Array.isArray(embededPatchInfo.patches)) { - embededPatchesInfo = embededPatchInfo.patches.map((embededPatchInfo) => _parseEmbededPatchInfo(embededPatchInfo)); + currentEmbededPatches = embededPatchInfo.patches.map((embededPatchInfo) => _parseEmbededPatchInfo(embededPatchInfo)); } else { console.warn('Rom Patcher JS: Invalid patches object for embeded patch', embededPatchInfo); } } else { - embededPatchesInfo = [_parseEmbededPatchInfo(embededPatchInfo)]; + currentEmbededPatches = [_parseEmbededPatchInfo(embededPatchInfo)]; } - loadingSpan.innerHTML = _('Unzipping...') + ' ' + spinnerHtml; - ZIPManager.unzipEmbededPatches(arrayBuffer, embededPatchesInfo); + htmlElements.setText('span-loading-embeded-patch', _('Unzipping...') + ' ' + spinnerHtml); + + ZIPManager.unzipEmbededPatches(arrayBuffer, currentEmbededPatches); } else { - embededPatchesInfo = [_parseEmbededPatchInfo(embededPatchInfo)]; - loadingSpan.innerHTML = embededPatchesInfo[0].name; - _setPatchInputSpinner(false); + const parsedPatch = _parseEmbededPatchInfo(embededPatchInfo); + + currentEmbededPatches = [parsedPatch]; + const option = document.createElement('option'); + option.innerHTML = parsedPatch.name; + htmlElements.get('select-patch').appendChild(option); + htmlElements.setEnabled('select-patch', false); + htmlElements.addClass('select-patch', 'single'); + htmlElements.hide('span-loading-embeded-patch'); + htmlElements.show('select-patch'); + fetchedFile.fileName = embededPatchInfo.file; RomPatcherWeb.providePatchFile(fetchedFile); } + isFetching = false; }) .catch(function (evt) { + isFetching = false; _setToastError((_('Error downloading %s') + '
' + evt.message).replace('%s', embededPatchInfo.file.replace(/^.*[\/\\]/g, ''))); }); }; const _getEmbededPatchInfo = function (fileName) { - if (embededPatchesInfo) - return embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === fileName); + if (currentEmbededPatches) + return currentEmbededPatches.find((embededPatchInfo) => embededPatchInfo.file === fileName); return null; } @@ -187,13 +201,17 @@ var RomPatcherWeb = (function () { return hexString } - const _setElementsStatus = function (status) { + const _setElementsStatus = function (status, applyButtonStatus) { htmlElements.setEnabled('input-file-rom', status); htmlElements.setEnabled('input-file-patch', status); - htmlElements.setEnabled('select-file-patch', status); + if (htmlElements.get('select-patch')) { + htmlElements.setEnabled('select-patch', htmlElements.get('select-patch').children.length > 1 ? status : false); + } htmlElements.setEnabled('checkbox-alter-header', status); - if (romFile && status && (patch /* || embededPatchesInfo */)) { + if (romFile && patch && status) { + if (settings.requireValidation && typeof applyButtonStatus !== 'undefined') + status = !!applyButtonStatus; htmlElements.setEnabled('button-apply', status); } else { htmlElements.setEnabled('button-apply', false); @@ -201,7 +219,7 @@ var RomPatcherWeb = (function () { }; const _setInputFileSpinner = function (inputFileId, status) { - const elementId = embededPatchesInfo && inputFileId === 'patch' ? ('select-file-' + inputFileId) : ('input-file-' + inputFileId); + const elementId = currentEmbededPatches && inputFileId === 'patch' ? ('select-' + inputFileId) : ('input-file-' + inputFileId); const spinnerId = 'spinner-' + inputFileId; htmlElements.removeClass(elementId, 'empty'); @@ -213,8 +231,13 @@ var RomPatcherWeb = (function () { spinner.className = 'rom-patcher-spinner'; const htmlInputFile = htmlElements.get(elementId); - if (htmlInputFile) - htmlInputFile.parentElement.appendChild(spinner); + if (htmlInputFile){ + if(elementId === 'select-patch'){ + htmlInputFile.parentElement.insertBefore(spinner, htmlElements.get('span-loading-embeded-patch')); + }else{ + htmlInputFile.parentElement.appendChild(spinner); + } + } htmlElements.addClass(elementId, 'loading'); htmlElements.removeClass(elementId, 'valid'); @@ -313,6 +336,10 @@ var RomPatcherWeb = (function () { document.getElementById('rom-patcher-' + id).innerHTML = text; }, + empty: function (id) { + if (document.getElementById('rom-patcher-' + id)) + document.getElementById('rom-patcher-' + id).innerHTML = ''; + }, addClass: function (id, className) { if (document.getElementById('rom-patcher-' + id)) document.getElementById('rom-patcher-' + id).classList.add(className); @@ -360,10 +387,25 @@ var RomPatcherWeb = (function () { htmlElements.enableAll(); _setApplyButtonSpinner(false); if (event.data.patchedRomU8Array && !event.data.errorMessage) { - const patchedRom = new BinFile(event.data.patchedRomU8Array.buffer); + var patchedRom = new BinFile(event.data.patchedRomU8Array.buffer); patchedRom.fileName = event.data.patchedRomFileName; + + if(currentEmbededPatches){ + const optionalPatches = currentEmbededPatches.filter((embededPatchInfo) => embededPatchInfo.optional); + if(optionalPatches.length){ + const originalFileName = patchedRom.fileName; + for(var i=0; i { // listen for events from the worker _setToastError('webWorkerCrc error: ' + event.message); @@ -447,22 +489,29 @@ var RomPatcherWeb = (function () { return missingDependencies; } - const _initialize = function (newSettings, embededPatchInfo) { - /* embeded patches */ - var validEmbededPatch = false; + + + + const _checkEmbededPatchParameter = function (embededPatchInfo) { if (embededPatchInfo) { if (typeof embededPatchInfo === 'string') embededPatchInfo = { file: embededPatchInfo }; - if (typeof embededPatchInfo === 'object') { - if (typeof embededPatchInfo.file === 'string') { - validEmbededPatch = true; - } else { - throw new Error('Rom Patcher JS: invalid embeded patch file'); - } - } + if (typeof embededPatchInfo !== 'object') + throw new Error('Rom Patcher JS: invalid embeded patch parameter'); + else if (typeof embededPatchInfo.file !== 'string') + throw new Error('Rom Patcher JS: embeded patch missing file property'); + + return embededPatchInfo; } + return false; + } + + const _initialize = function (newSettings, embededPatchInfo) { + /* embeded patches */ + var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo); + /* check if Rom Patcher JS core is available */ @@ -489,14 +538,34 @@ var RomPatcherWeb = (function () { } else { throw new Error('Rom Patcher JS: input#rom-patcher-input-file-rom[type=file] not found'); } - const htmlInputFilePatch = htmlElements.get('input-file-patch'); - if (htmlInputFilePatch && htmlInputFilePatch.tagName === 'INPUT' && htmlInputFilePatch.type === 'file') { - htmlInputFilePatch.addEventListener('change', function (evt) { - htmlElements.disableAll(); - new BinFile(this, RomPatcherWeb.providePatchFile); - }); + if (validEmbededPatch) { + const htmlSelectPatch = htmlElements.get('select-patch'); + if (htmlSelectPatch && htmlSelectPatch.tagName === 'SELECT') { + htmlSelectPatch.addEventListener('change', function (evt) { + const zippedEntryIndex = parseInt(this.value); + this._unzipSelectedPatch(zippedEntryIndex); + }); + } else { + throw new Error('Rom Patcher JS: select#rom-patcher-select-patch not found'); + } + const loadingSpan = document.createElement('span'); + loadingSpan.id = 'rom-patcher-span-loading-embeded-patch'; + loadingSpan.style.display = 'none'; + htmlSelectPatch.parentElement.appendChild(loadingSpan); + const containerOptionalPatches = document.createElement('div'); + containerOptionalPatches.id = 'rom-patcher-container-optional-patches'; + containerOptionalPatches.style.display = 'none'; + htmlSelectPatch.parentElement.appendChild(containerOptionalPatches); } else { - throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found'); + const htmlInputFilePatch = htmlElements.get('input-file-patch'); + if (htmlInputFilePatch && htmlInputFilePatch.tagName === 'INPUT' && htmlInputFilePatch.type === 'file') { + htmlInputFilePatch.addEventListener('change', function (evt) { + htmlElements.disableAll(); + new BinFile(this, RomPatcherWeb.providePatchFile); + }); + } else { + throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found'); + } } const htmlButtonApply = htmlElements.get('button-apply'); if (htmlButtonApply && htmlButtonApply.tagName === 'BUTTON') { @@ -558,9 +627,11 @@ var RomPatcherWeb = (function () { htmlInputFileRom.addEventListener('drop', function (evt) { evt.stopPropagation(); }); - htmlInputFilePatch.addEventListener('drop', function (evt) { - evt.stopPropagation(); - }); + if (!validEmbededPatch) { + htmlElements.get('input-file-patch').addEventListener('drop', function (evt) { + evt.stopPropagation(); + }); + } } console.log('Rom Patcher JS initialized'); @@ -572,9 +643,12 @@ var RomPatcherWeb = (function () { /* download embeded patch */ if (validEmbededPatch) - _fetchPatchFile(embededPatchInfo); + _fetchPatchFile(validEmbededPatch); else htmlElements.enableAll(); + + if (typeof settings.oninitialize === 'function') + settings.oninitialize(this); } @@ -597,7 +671,7 @@ var RomPatcherWeb = (function () { return initialized; }, getEmbededPatches: function () { - return embededPatchesInfo; + return currentEmbededPatches; }, provideRomFile: function (binFile, transferFakeFile) { @@ -766,21 +840,23 @@ var RomPatcherWeb = (function () { }, pickEmbededFile: function (fileName) { - if (typeof fileName !== 'string') + if(!currentEmbededPatches) + throw new Error('No embeded patches available'); + else if (typeof fileName !== 'string') throw new Error('Invalid embeded patch file name'); - const selectFilePatch = htmlElements.get('select-file-patch'); - if (selectFilePatch) { - const embededPatchInfo = _getEmbededPatchInfo(fileName); - if (embededPatchInfo && typeof embededPatchInfo.selectIndex === 'number' && selectFilePatch.value != embededPatchInfo.selectIndex) { - selectFilePatch.value = embededPatchInfo.selectIndex; - - /* create and dispatch change event */ - const evt = new Event('change'); - selectFilePatch.dispatchEvent(evt); + const selectPatch = htmlElements.get('select-patch'); + for(var i=0; i embededPatchInfo.file === filteredEntries[i].filename); - var option = document.createElement('option'); - option.innerHTML = embededPatchInfo ? embededPatchInfo.name : filteredEntries[i].filename; - option.value = i; - select.appendChild(option); - if (embededPatchInfo) { - embededPatchInfo.selectIndex = i; - } - } - - select.addEventListener('change', function (evt) { - const fileIndex = parseInt(this.value); - _unzipEntry(filteredEntries[fileIndex], romPatcherWeb.providePatchFile); - }); - } else { - throw new Error('rom-patcher-select-file-patch not found'); - } + const selectablePatches = []; + const optionalPatches = []; + for (var i = 0; i < filteredEntries.length; i++) { + const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === filteredEntries[i].filename); + if (embededPatchInfo && embededPatchInfo.optional) + optionalPatches.push(filteredEntries[i]); + else + selectablePatches.push(filteredEntries[i]); } - //_setPatchInputSpinner(false); - _unzipEntry(filteredEntries[0], romPatcherWeb.providePatchFile); + if (!selectablePatches.length) { + romPatcherWeb.setErrorMessage(_('No valid non-optional patches found in ZIP'), 'error'); + romPatcherWeb.disable(); + throw new Error('No valid non-optional patches found in ZIP'); + } + + if (embededPatchesInfo.length && embededPatchesInfo.length === 1 && selectablePatches.length === 1) + embededPatchesInfo[0].file = selectablePatches[0].filename; + + for (var i = 0; i < selectablePatches.length; i++) { + const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === selectablePatches[i].filename); + const option = document.createElement('option'); + option.innerHTML = embededPatchInfo && embededPatchInfo.name ? embededPatchInfo.name : selectablePatches[i].filename; + option.value = i; + option.patchFileName = selectablePatches[i].filename; + htmlElements.get('select-patch').appendChild(option); + } + htmlElements.get('select-patch')._unzipSelectedPatch = function(fileIndex){ + _unzipEntry(selectablePatches[fileIndex], romPatcherWeb.providePatchFile); + }; + + for (var i = 0; i < optionalPatches.length; i++) { + const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === optionalPatches[i].filename); + + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.value = i; + checkbox.checked = false; + checkbox.disabled = true; + embededPatchInfo.checkbox = checkbox; + + const label = document.createElement('label'); + label.className = 'rom-patcher-checkbox-optional-patch'; + label.appendChild(checkbox); + label.appendChild(document.createTextNode(embededPatchInfo.name || embededPatchInfo.file)); + if (embededPatchInfo.description) + label.title = embededPatchInfo.description; + + htmlElements.get('container-optional-patches').appendChild(label); + + optionalPatches[i].getData(new zip.BlobWriter(), function (blob) { + const fileReader = new FileReader(); + fileReader.onload = function () { + const binFile = new BinFile(this.result); + binFile.fileName = 'optional_patch.unk'; + embededPatchInfo.parsedPatch = RomPatcher.parsePatchFile(binFile); + checkbox.disabled = false; + }; + fileReader.readAsArrayBuffer(blob); + }); + } + if (optionalPatches.length === 1) + htmlElements.show('container-optional-patches'); + + + + if (selectablePatches.length === 1) + htmlElements.addClass('select-patch', 'single'); + else + htmlElements.addClass('select-patch', 'multiple'); + + htmlElements.setEnabled('select-patch', false); + htmlElements.hide('span-loading-embeded-patch'); + htmlElements.show('select-patch'); + + _unzipEntry(selectablePatches[0], romPatcherWeb.providePatchFile); + } else { romPatcherWeb.setErrorMessage(_('No valid patches found in ZIP'), 'error'); romPatcherWeb.disable(); diff --git a/rom-patcher-js/style.css b/rom-patcher-js/style.css index 1265ccd..1465f9d 100644 --- a/rom-patcher-js/style.css +++ b/rom-patcher-js/style.css @@ -356,6 +356,22 @@ +#rom-patcher-container #rom-patcher-select-patch{ + display:none +} +#rom-patcher-container #rom-patcher-select-patch.single{ + background-image: none; + background-color: transparent; + color: inherit !important; + padding-left: 0; +} + + + + + + +