Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fcf56db
Add dev/js/prototype_mode config setting (full|shim|none)
Mar 16, 2026
3a87a8b
Add conditional Prototype/Scriptaculous loading in Head block
Mar 16, 2026
4f8046e
Add Prototype.js compatibility shim and deprecation wrapper
Mar 16, 2026
a88ef41
Rewrite loader.js and events.js to vanilla JS (Wave 1)
Mar 16, 2026
3e1ac3e
Rewrite translate.js, accordion.js, and varien/js.js to vanilla JS (W…
Mar 16, 2026
c7f569b
Rewrite frontend critical path JS files to vanilla JS (Wave 3)
Mar 16, 2026
1f58d6f
Rewrite admin tools, accordion, tabs, form, and grid to vanilla JS (W…
Mar 16, 2026
42475c4
Rewrite admin high-complexity JS files to vanilla JS (Wave 5)
Mar 16, 2026
5651fd5
Rewrite validation and remaining JS files to vanilla JS (Wave 6)
Mar 16, 2026
b20cf7a
Rewrite inline Prototype.js patterns in 170 .phtml templates (Wave 7)
Mar 16, 2026
6891175
Update prototype-migration.md with implementation status and next steps
Mar 16, 2026
fc60e8d
Rewrite remaining .phtml template inline Prototype patterns (Wave 7b)
Mar 24, 2026
3468003
Remove Prototype.js and Scriptaculous, switch default to shim (Phase 3)
Mar 24, 2026
f68de65
Fix shim gsub to pass array-like match object to callbacks
Mar 24, 2026
cee4d94
Add missing shim APIs found via Cypress testing
Apr 6, 2026
0fb5030
Rewrite varien JS and skin checkout scripts to vanilla JS (Wave 8)
danidgo Jun 1, 2026
73bcff0
Rewrite adminhtml templates and JS to vanilla JS (Wave 9)
danidgo Jun 10, 2026
1ed5ed0
Add prototype_mode (full/shim/none) support and rewrite admin JS to v…
danidgo Jun 29, 2026
d6b58bd
Continue Prototype.js -> vanilla JS migration and fix related regress…
danidgo Jul 13, 2026
6de4cb1
Default prototype_mode to full for backward compatibility
danidgo Jul 16, 2026
efe10ed
Restore Prototype/Scriptaculous libraries for prototype_mode=full
danidgo Jul 16, 2026
cce212e
Decouple ExtJS admin tree from Prototype.js and fix related runtime bugs
danidgo Jul 16, 2026
9b98c5a
Rewrite remaining USPS/checkout JS to vanilla for prototype_mode=none
danidgo Jul 17, 2026
51f54d8
Fix prototype_mode=none regressions found via Cypress
danidgo Jul 17, 2026
34cc353
Fix CI failures: replace regex HTML sanitizers with DOM parsing, addr…
Jul 17, 2026
1cbe8ca
Fix remaining spellcheck failures in prototype-migration doc
Jul 17, 2026
6050338
Apply Rector fixes and escape translated label for Sonar
Jul 17, 2026
debd6b6
Fix shim fidelity and vanilla-JS regressions found in two-pass review
Jul 18, 2026
2d1d7a4
Add Cypress coverage for prototype_mode shim and none
Jul 18, 2026
dd887cc
Pin ddev setup action to full commit SHA for SonarCloud S7637
Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 21 additions & 0 deletions .github/spellcheck-wordlist.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ACL
ActionScript
analytics
APIs
bool
boolean
backorders
Expand All @@ -12,18 +13,23 @@ Cloudflare
CMS
Cron
CVE
Centinel
CodeQL
compat
config
DevOps
DDEV
DNS
DocBlock
DOM
EAV
Emmet
ExtJS
FireGento
FPC
frontend
Gitpod
globals
HiPay
Homebrew
HMAC
Expand All @@ -32,8 +38,10 @@ HTTPS
ImageMagick
IntelliSense
jQuery
js
JS
JSON
lifecycle
LTS
macOS
Magento
Expand All @@ -43,29 +51,36 @@ mkcert
MkDocs
Matomo
MTF
namespace
nginx
npm
OAuth
OOP
OpenMage
OpenNode
PageSpeed
param
PHPCompatibility
PHPCS
PHPMD
phpMyAdmin
PHPStan
PhpStorm
phtml
PHPUnit
PLAINTEXT
programmatically
RCE
reCaptcha
Redis
repo
RPC
RSS
RWD
runtime
SCSS
scriptaculous
Scriptaculous
SHA
sku
SKU
Expand All @@ -74,8 +89,14 @@ SMTP
SSL
TinyMCE
toc
UI
URI
un
unminified
uploader
validator
validators
varien
Varien
VMware
WAMP
Expand Down
45 changes: 44 additions & 1 deletion .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v7
- name: Setup DDEV
uses: ddev/github-action-setup-ddev@v1
uses: ddev/github-action-setup-ddev@fdf2f5c97943bae638f31df6df86f1defa6210c0 # v1.12.1
with:
autostart: false

Expand Down Expand Up @@ -44,3 +44,46 @@ jobs:
with:
name: cypress-screenshots
path: cypress/screenshots

# Same suite, but with dev/js/prototype_mode overridden so the vanilla-JS
# rewrites run against the compatibility shim ("shim") and with no Prototype
# layer at all ("none"). The default job above covers "full".
test-prototype-mode:
name: Cypress (prototype_mode ${{ matrix.prototype_mode }})
runs-on: [ubuntu-latest]
strategy:
fail-fast: false
matrix:
prototype_mode: ['shim', 'none']

steps:
- uses: actions/checkout@v7
- name: Setup DDEV
uses: ddev/github-action-setup-ddev@fdf2f5c97943bae638f31df6df86f1defa6210c0 # v1.12.1
with:
autostart: false

# install DDEV configuration
- run: ddev config --project-type=magento --php-version=8.3 --webserver-type=nginx-fpm --web-environment="MAGE_IS_DEVELOPER_MODE=1,OPENMAGE_CONFIG_OVERRIDE_ALLOWED=1,OPENMAGE_CONFIG__DEFAULT__DEV__JS__PROTOTYPE_MODE=${{ matrix.prototype_mode }},OPENMAGE_CONFIG__DEFAULT__GENERAL__STORE_INFORMATION__NAME=ENV name default,OPENMAGE_CONFIG__WEBSITES__BASE__GENERAL__STORE_INFORMATION__PHONE=ENV phone website,OPENMAGE_CONFIG__STORES__GERMAN__GENERAL__STORE_INFORMATION__ADDRESS=ENV address store"

# install composer dependencies
- run: ddev composer install

# install openmage
- run: ddev openmage-install -q

# install cypress-addon
- run: ddev add-on get tyler36/ddev-cypress

# start ddev
- run: ddev start

# run cypress
- run: ddev cypress-run --config-file .cypress.config.js

- name: Upload screenshots
uses: actions/upload-artifact@v7
if: ${{ !success() }}
with:
name: cypress-screenshots-${{ matrix.prototype_mode }}
path: cypress/screenshots
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function getToggleCode()
{
$htmlId = 'use_config_' . $this->getHtmlId();
return 'toggleValueElements(this, this.parentNode.parentNode);'
. "if (!this.checked) toggleValueElements($('{$htmlId}'), $('{$htmlId}').parentNode);";
. "if (!this.checked) toggleValueElements(document.getElementById('{$htmlId}'), document.getElementById('{$htmlId}').parentNode);";
}

/**
Expand Down Expand Up @@ -57,7 +57,7 @@ public function getElementHtml()
$html .= ' <label for="' . $htmlId . '" class="normal">'
. Mage::helper('adminhtml')->__('Use Config Settings') . '</label>';

return $html . ('<script type="text/javascript">toggleValueElements($(\'' . $htmlId . '\'), $(\'' . $htmlId
return $html . ('<script type="text/javascript">toggleValueElements(document.getElementById(\'' . $htmlId . "'), document.getElementById('" . $htmlId
. "').parentNode);" . '</script>');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function getToggleCode()
{
$htmlId = 'use_config_' . $this->getHtmlId();
return 'toggleValueElements(this, this.parentNode.parentNode);'
. "if (!this.checked) toggleValueElements($('{$htmlId}'), $('{$htmlId}').parentNode);";
. "if (!this.checked) toggleValueElements(document.getElementById('{$htmlId}'), document.getElementById('{$htmlId}').parentNode);";
}

/**
Expand Down Expand Up @@ -55,7 +55,7 @@ public function getElementHtml()
$html .= ' <label for="' . $htmlId . '" class="normal">'
. Mage::helper('adminhtml')->__('Use All Available Attributes') . '</label>';

return $html . ('<script type="text/javascript">toggleValueElements($(\'' . $htmlId . '\'), $(\'' . $htmlId
return $html . ('<script type="text/javascript">toggleValueElements(document.getElementById(\'' . $htmlId . "'), document.getElementById('" . $htmlId
. "').parentNode);</script>");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function getToggleCode()
{
$htmlId = 'use_config_' . $this->getHtmlId();
return 'toggleValueElements(this, this.parentNode.parentNode);'
. "if (!this.checked) toggleValueElements($('{$htmlId}'), $('{$htmlId}').parentNode);";
. "if (!this.checked) toggleValueElements(document.getElementById('{$htmlId}'), document.getElementById('{$htmlId}').parentNode);";
}

/**
Expand Down Expand Up @@ -56,7 +56,7 @@ public function getElementHtml()
$html .= ' <label for="' . $htmlId . '" class="normal">'
. Mage::helper('adminhtml')->__('Use Config Settings') . '</label>';

return $html . ('<script type="text/javascript">toggleValueElements($(\'' . $htmlId . '\'), $(\'' . $htmlId
return $html . ('<script type="text/javascript">toggleValueElements(document.getElementById(\'' . $htmlId . "'), document.getElementById('" . $htmlId
. "').parentNode);</script>");
}
}
4 changes: 2 additions & 2 deletions app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ public function getBreadcrumbsJavascript($path, $javascriptVarName)
'<script type="text/javascript">'
. $javascriptVarName . ' = ' . Mage::helper('core')->jsonEncode($categories) . ';'
. ($this->canAddSubCategory()
? '$("add_subcategory_button").show();'
: '$("add_subcategory_button").hide();')
? 'document.getElementById("add_subcategory_button").style.display = "";'
: 'document.getElementById("add_subcategory_button").style.display = "none";')
. '</script>';
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function getElementHtml()
$html .= ' onclick="toggleValueElements(this, this.parentNode);" class="checkbox" type="checkbox" />';
$html .= ' <label for="' . $htmlId . '">' . Mage::helper('adminhtml')->__('Use Config Settings') . '</label>';

return $html . ('<script type="text/javascript">toggleValueElements($(\'' . $htmlId . '\'), $(\'' . $htmlId . "').parentNode);</script>");
return $html . ('<script type="text/javascript">toggleValueElements(document.getElementById(\'' . $htmlId . "'), document.getElementById('" . $htmlId . "').parentNode);</script>");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ public function getCheckboxCheckCallback()
{
if ($this->getUseMassaction()) {
return "function (grid, element) {
$(grid.containerId).fire('product:changed', {element: element});
var ev = new CustomEvent('product:changed', {bubbles: true, cancelable: true});
ev.memo = {element: element};
document.getElementById(grid.containerId).dispatchEvent(ev);
}";
}

Expand All @@ -119,9 +121,10 @@ public function getRowClickCallback()
$chooserJsObject = $this->getId();
return '
function (grid, event) {
var trElement = Event.findElement(event, "tr");
var productId = trElement.down("td").innerHTML;
var productName = trElement.down("td").next().next().innerHTML;
var trElement = event.target.closest("tr");
var cells = trElement.querySelectorAll("td");
var productId = cells[0].innerHTML;
var productName = cells[2].innerHTML;
var optionLabel = productName;
var optionValue = "product/" + productId.replace(/^\s+|\s+$/g,"");
if (grid.categoryId) {
Expand Down
2 changes: 1 addition & 1 deletion app/code/core/Mage/Adminhtml/Block/Cms/Block/Edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function toggleEditor() {
}

function saveAndContinueEdit(){
editForm.submit($('edit_form').action+'back/edit/');
editForm.submit(document.getElementById('edit_form').action+'back/edit/');
}
";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ public function getRowClickCallback()
$chooserJsObject = $this->getId();
return '
function (grid, event) {
var trElement = Event.findElement(event, "tr");
var blockId = trElement.down("td").innerHTML.replace(/^\s+|\s+$/g,"");
var blockTitle = trElement.down("td").next().innerHTML;
var trElement = event.target.closest("tr");
var cells = trElement.querySelectorAll("td");
var blockId = cells[0].innerHTML.replace(/^\s+|\s+$/g,"");
var blockTitle = cells[1].innerHTML;
' . $chooserJsObject . '.setElementValue(blockId);
' . $chooserJsObject . '.setElementLabel(blockTitle);
' . $chooserJsObject . '.close();
Expand Down
5 changes: 3 additions & 2 deletions app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ function saveAndContinueEdit(urlTemplate) {
if (tabsIdValue.startsWith(tabsBlockPrefix)) {
tabsIdValue = tabsIdValue.substr(tabsBlockPrefix.length)
}
var template = new Template(urlTemplate, /(^|.|\\r|\\n)({{(\w+)}})/);
var url = template.evaluate({tab_id:tabsIdValue});
var url = urlTemplate.replace(/{{(\\w+)}}/g, function(match, key) {
return key === 'tab_id' ? tabsIdValue : match;
});
editForm.submit(url);
}
";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ public function getRowClickCallback()
$chooserJsObject = $this->getId();
return '
function (grid, event) {
var trElement = Event.findElement(event, "tr");
var pageTitle = trElement.down("td").next().innerHTML;
var pageId = trElement.down("td").innerHTML.replace(/^\s+|\s+$/g,"");
var trElement = event.target.closest("tr");
var cells = trElement.querySelectorAll("td");
var pageTitle = cells[1].innerHTML;
var pageId = cells[0].innerHTML.replace(/^\s+|\s+$/g,"");
' . $chooserJsObject . '.setElementValue(pageId);
' . $chooserJsObject . '.setElementLabel(pageTitle);
' . $chooserJsObject . '.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,54 @@ protected function _getScriptHtml(Varien_Data_Form_Element_Abstract $element)
return <<<SCRIPT
<script type="text/javascript">
//<![CDATA[
$$('#_accountnew_password,#account-send-pass').each(function(elem) {
$(elem).on('change', function() {
if ($('_accountnew_password').getValue() || $('account-send-pass').checked) {
$('{$element->getHtmlId()}_container').show();
$('{$element->getHtmlId()}').enable();
} else {
$('{$element->getHtmlId()}_container').hide();
$('{$element->getHtmlId()}').disable();
}
if ($('email-passowrd-warning')) {
if (!$('_accountnew_password').getValue() || $('account-send-pass').checked) {
$('email-passowrd-warning').hide();
} else if ($('_accountnew_password').getValue()) {
$('email-passowrd-warning').show();
}
}
});
$(elem).on('focus', function() {
$('{$element->getHtmlId()}_container').show();
$('{$element->getHtmlId()}').enable();
});
$(elem).on('blur', function() {
if (!$('_accountnew_password').getValue() && !$('account-send-pass').checked) {
$('{$element->getHtmlId()}_container').hide();
$('{$element->getHtmlId()}').disable();
}
});
document.observe("dom:loaded", function() {
$('{$element->getHtmlId()}_container').hide();
$('{$element->getHtmlId()}').disable();
});
(function() {
var newPassEl = document.getElementById('_accountnew_password');
var sendPassEl = document.getElementById('account-send-pass');

function getContainer() { return document.getElementById('{$element->getHtmlId()}_container'); }
function getInput() { return document.getElementById('{$element->getHtmlId()}'); }

function showAdminPass() {
var c = getContainer(), i = getInput();
if (c) { c.style.display = ''; }
if (i) { i.disabled = false; }
}

function hideAdminPass() {
var c = getContainer(), i = getInput();
if (c) { c.style.display = 'none'; }
if (i) { i.disabled = true; }
}

function onChange() {
var hasNewPass = newPassEl && newPassEl.value;
var sendPass = sendPassEl && sendPassEl.checked;
if (hasNewPass || sendPass) {
showAdminPass();
} else {
hideAdminPass();
}
var warning = document.getElementById('email-passowrd-warning');
if (warning) {
warning.style.display = (!hasNewPass || sendPass) ? 'none' : '';
}
}

function onBlur() {
if ((!newPassEl || !newPassEl.value) && (!sendPassEl || !sendPassEl.checked)) {
hideAdminPass();
}
}

[newPassEl, sendPassEl].forEach(function(elem) {
if (!elem) { return; }
elem.addEventListener('change', onChange);
elem.addEventListener('focus', showAdminPass);
elem.addEventListener('blur', onBlur);
});

document.addEventListener('DOMContentLoaded', hideAdminPass);
})();
//]]></script>
SCRIPT;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function render(Varien_Data_Form_Element_Abstract $element)
$html .= '</select>';

$html .= '<script type="text/javascript">' . "\n";
$html .= '$("' . $selectId . '").setAttribute("defaultValue", "' . $regionId . '");' . "\n";
$html .= 'document.getElementById("' . $selectId . '").setAttribute("defaultValue", "' . $regionId . '");' . "\n";
$html .= 'new regionUpdater("' . $country->getHtmlId() . '", "' . $element->getHtmlId() . '", "'
. $selectId . '", ' . Mage::helper('directory')->getRegionJsonByStore($quoteStoreId) . ');' . "\n";
$html .= '</script>' . "\n";
Expand Down
Loading
Loading