Explorer Page and Module Finder for your browser - Mendix Forum

Explorer Page and Module Finder for your browser

5

Hi all!

I've created a simple new bookmarklet that allows you to get the module and page name of the explorer and display it in your browser. This will allow you to easily find the same page you're looking at in the browser, in your Mendix explorer.

 

Back in the day we used to have one that worked perfectly, however, with the new React modeler, the older version didn't work. This new version supports both the new React and Dojo versions :)!

 

History:

v1.1: Initial release

v1.2: Added browser support, included Dojo compatibility

v1.3: Popup support

v1.4: Fixed Dojo Popup Bug / Added Styled Version

 

Example of the returned message:

image.png

 

How it works:

1. Go to your favourite browser and press add a new bookmark.

2. Set the name as Mendix Page Finder (or something similar)

3. Inside the URL section; paste one of the javascripts I added underneath (Minimal or Styled)

4. Open both a Dojo (Mx 9) and or React (Mx 11) modeler project and see your page name (you can even try it on the community pages here ;) )

5. The page name is automatically pasted to your clipboard

6. Go to your Mendix Modeler, paste the name inside the explorer search field and that's the page you were looking at in the browser (if a page is not a Mendix based page, the javascript returns Unknown. 

7. If it works, feel free to like this post. If it doesn't, please let me know which browser you are using and what is happening. I will look into it for you!

 

v1.4 (Minimal Version)

javascript:(function(){let pageName = 'Unknown';let isPopup = false;try{const activeModal = document.querySelector('.modal-dialog');if(activeModal){isPopup = true;const allElementsWithIds = activeModal.querySelectorAll('[id],[data-button-id]');let foundPageName = false;for(const element of allElementsWithIds){const idValue = element.id || element.getAttribute('data-button-id');if(!idValue)continue;const parts = idValue.split('.');if(parts.length >= 3){if(parts[0] === 'p'){pageName = parts[1] + '.' + parts[2];foundPageName = true;break;}else if(/^\d+$/.test(parts[0])){pageName = parts[1] + '.' + parts[2];foundPageName = true;break;}}}if(!foundPageName){pageName = 'EmptyPopup';}}if(!isPopup || pageName === 'Unknown'){isPopup = false;if(window.history && window.history.state && window.history.state.pageName){pageName = window.history.state.pageName;}else if(typeof window.mx !== 'undefined' && window.mx.ui && typeof window.mx.ui.getContentForm === 'function'){const contentForm = window.mx.ui.getContentForm();if(contentForm && contentForm.path){pageName = contentForm.path;}}else if(typeof window.dijit !== 'undefined' && window.dijit.registry){const forms = [];window.dijit.registry.forEach(function(widget){if(widget.declaredClass && widget.declaredClass.indexOf('mxui.lib.MxContext')> -1){if(widget._form && widget._form._formPath){forms.push(widget._form._formPath);}}});if(forms.length > 0){pageName = forms[0];}}if(pageName === 'Unknown'){const pageElements = document.querySelectorAll('[data-pagename],[data-page],[data-page-name],[mx-name-page]');if(pageElements.length > 0){for(const elem of pageElements){const name = elem.getAttribute('data-pagename')|| elem.getAttribute('data-page')|| elem.getAttribute('data-page-name')|| elem.getAttribute('mx-name-page');if(name){pageName = name;break;}}}}}}catch(error){pageName = 'Error:' + error.message;}let moduleName = 'Unknown';let pageNameOnly = 'Unknown';let isEmptyPopup = false;if(pageName === 'EmptyPopup'){isEmptyPopup = true;moduleName = 'Unable to detect';pageNameOnly = 'Empty popup';}else if(pageName !== 'Unknown'){let cleanedPath = pageName.replace(/\.page\.xml$/i,'');cleanedPath = cleanedPath.split('/').join('.');if(cleanedPath.includes('.')){const parts = cleanedPath.split('.');if(parts.length >= 2){moduleName = parts[0];pageNameOnly = parts.slice(1).join('.');}else{pageNameOnly = parts[0];}}else{pageNameOnly = cleanedPath;}}let copyStatus = '';if(!isEmptyPopup){try{const textArea = document.createElement('textarea');textArea.value = pageNameOnly;textArea.style.position = 'fixed';textArea.style.left = '-999999px';textArea.style.top = '-999999px';document.body.appendChild(textArea);textArea.focus();textArea.select();document.execCommand('copy');document.body.removeChild(textArea);copyStatus = '\n\n✓ Copied to clipboard:' + pageNameOnly;}catch(e){copyStatus = '\n\n(Copy failed)';}}const popupLabel = isPopup ? %27 [POPUP]%27:%27%27;let message = %27Module:%27 + moduleName + %27\nPage name:%27 + pageNameOnly + popupLabel;if(isEmptyPopup){message += %27\n\n⚠ EMPTY POPUP DETECTED\nThis popup has no widgets.\nAdd a widget to detect the page name.%27;}else{message += copyStatus;}alert(message);})();

 

v1.4 (Styled Version)

javascript:(function(){'use strict';let pageName = 'Unknown';let isPopup = false;try{const activeModal = document.querySelector('.modal-dialog');if(activeModal){isPopup = true;const allElementsWithIds = activeModal.querySelectorAll('[id],[data-button-id]');let foundPageName = false;for(const element of allElementsWithIds){const idValue = element.id || element.getAttribute('data-button-id');if(!idValue)continue;const parts = idValue.split('.');if(parts.length >= 3){if(parts[0] === 'p'){pageName = parts[1] + '.' + parts[2];foundPageName = true;break;}else if(/^\d+$/.test(parts[0])){pageName = parts[1] + '.' + parts[2];foundPageName = true;break;}}}if(!foundPageName){pageName = 'EmptyPopup';}}if(!isPopup || pageName === 'Unknown'){isPopup = false;if(window.history && window.history.state && window.history.state.pageName){pageName = window.history.state.pageName;}else if(typeof window.mx !== 'undefined' && window.mx.ui && typeof window.mx.ui.getContentForm === 'function'){const contentForm = window.mx.ui.getContentForm();if(contentForm && contentForm.path){pageName = contentForm.path;}}else if(typeof window.dijit !== 'undefined' && window.dijit.registry){const forms = [];window.dijit.registry.forEach(function(widget){if(widget.declaredClass && widget.declaredClass.indexOf('mxui.lib.MxContext')> -1){if(widget._form && widget._form._formPath){forms.push(widget._form._formPath);}}});if(forms.length > 0){pageName = forms[0];}}if(pageName === 'Unknown'){const pageElements = document.querySelectorAll('[data-pagename],[data-page],[data-page-name],[mx-name-page]');if(pageElements.length > 0){for(const elem of pageElements){const name = elem.getAttribute('data-pagename')|| elem.getAttribute('data-page')|| elem.getAttribute('data-page-name')|| elem.getAttribute('mx-name-page');if(name){pageName = name;break;}}}}}}catch(error){pageName = 'Error:' + error.message;}let moduleName = 'Unknown';let pageNameOnly = 'Unknown';let isEmptyPopup = false;if(pageName === 'EmptyPopup'){isEmptyPopup = true;moduleName = 'Unable to detect';pageNameOnly = 'Empty popup detected';}else if(pageName !== 'Unknown'){let cleanedPath = pageName.replace(/\.page\.xml$/i,'');cleanedPath = cleanedPath.split('/').join('.');if(cleanedPath.includes('.')){const parts = cleanedPath.split('.');if(parts.length >= 2){moduleName = parts[0];pageNameOnly = parts.slice(1).join('.');}else{pageNameOnly = parts[0];}}else{pageNameOnly = cleanedPath;}}let autoCopied = false;const copyText = pageNameOnly;if(!isEmptyPopup){try{const textArea = document.createElement('textarea');textArea.value = copyText;textArea.style.position = 'fixed';textArea.style.left = '-999999px';textArea.style.top = '-999999px';document.body.appendChild(textArea);textArea.focus();textArea.select();try{const successful = document.execCommand('copy');autoCopied = successful;}catch(err){autoCopied = false;}document.body.removeChild(textArea);}catch(e){autoCopied = false;}if(navigator.clipboard && navigator.clipboard.writeText){navigator.clipboard.writeText(copyText).catch(function(){});}}const modal = document.createElement('div');modal.style.cssText = ` position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:white;padding:30px;border-radius:10px;box-shadow:0 4px 20px rgba(0,0,0,0.3);z-index:999999;max-width:600px;min-width:400px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;`;const title = document.createElement('h2');title.textContent = 'Mendix Page Finder';title.style.cssText = ` margin:0 0 20px 0;color:#0595DB;font-size:24px;font-weight:600;%60;if(isPopup){const popupBadge = document.createElement('span');popupBadge.textContent = 'POPUP';popupBadge.style.cssText = %60 background:#28a745;color:white;padding:3px 10px;border-radius:5px;font-size:12px;margin-left:10px;font-weight:600;%60;title.appendChild(popupBadge);}const moduleLabel = document.createElement('div');moduleLabel.textContent = 'Module:';moduleLabel.style.cssText = %60 font-weight:600;margin-bottom:8px;color:#333;font-size:14px;%60;const moduleValue = document.createElement('div');moduleValue.textContent = moduleName;moduleValue.style.cssText = %60 padding:12px 15px;background:#f5f5f5;border-radius:5px;border:1px solid #ddd;font-family:'Consolas','Monaco','Menlo','Source Code Pro','Courier New',monospace;font-size:15px;word-break:break-all;margin-bottom:15px;color:#0595DB;font-weight:600;%60;const pageLabel = document.createElement('div');pageLabel.textContent = 'Page name:';pageLabel.style.cssText = %60 font-weight:600;margin-bottom:8px;color:#333;font-size:14px;%60;const pageValue = document.createElement('div');pageValue.textContent = pageNameOnly;pageValue.style.cssText = %60 padding:12px 15px;background:#f5f5f5;border-radius:5px;border:1px solid #ddd;font-family:'Consolas','Monaco','Menlo','Source Code Pro','Courier New',monospace;font-size:15px;word-break:break-all;margin-bottom:15px;color:#0595DB;font-weight:600;%60;let emptyPopupMessage = null;if(isEmptyPopup){emptyPopupMessage = document.createElement('div');emptyPopupMessage.style.cssText = %60 padding:12px 15px;background:#fff3cd;border:1px solid #ffc107;border-radius:5px;margin-bottom:15px;font-size:13px;color:#856404;line-height:1.5;%60;emptyPopupMessage.innerHTML = %60 <strong>⚠ Empty Popup Detected</strong><br> This popup has no widgets or content. To determine the page name,please add at least one widget(text,button,input,etc.)to the popup page in Mendix Studio Pro. %60;}const autocopiedNote = document.createElement('div');autocopiedNote.style.cssText = %60 padding:8px 12px;background:${isEmptyPopup ? '#f8d7da':(autoCopied ? '#d4edda':'#fff3cd')};border:1px solid ${isEmptyPopup ? '#f5c6cb':(autoCopied ? '#c3e6cb':'#ffc107')};border-radius:5px;margin-bottom:15px;font-size:12px;color:${isEmptyPopup ? '#721c24':(autoCopied ? '#155724':'#856404')};text-align:center;%60;if(isEmptyPopup){autocopiedNote.innerHTML = %60✗ Cannot copy - empty popup%60;}else{autocopiedNote.innerHTML = autoCopied ? %60✓ Copied to clipboard:<strong>${copyText}</strong>%60:%60⚠ Copy failed - use button below%60;}const copyButton = document.createElement('button');copyButton.textContent = 'Copy Page Name';copyButton.disabled = isEmptyPopup;copyButton.style.cssText = %60 background:${isEmptyPopup ? '#6c757d':'#0595DB'};color:white;border:none;padding:10px 20px;border-radius:5px;cursor:${isEmptyPopup ? 'not-allowed':'pointer'};font-size:14px;margin-right:10px;font-weight:500;opacity:${isEmptyPopup ? '0.6':'1'};%60;if(!isEmptyPopup){copyButton.onmouseover = function(){this.style.background = '#047ab8';};copyButton.onmouseout = function(){this.style.background = '#0595DB';};copyButton.onclick = function(){const textArea = document.createElement('textarea');textArea.value = copyText;textArea.style.position = 'fixed';textArea.style.left = '-999999px';document.body.appendChild(textArea);textArea.focus();textArea.select();try{document.execCommand('copy');copyButton.textContent = 'Copied!';autocopiedNote.style.background = '#d4edda';autocopiedNote.style.borderColor = '#c3e6cb';autocopiedNote.style.color = '#155724';autocopiedNote.innerHTML = %60✓ Copied to clipboard:<strong>${copyText}</strong>%60;setTimeout(function(){copyButton.textContent = 'Copy Page Name';},2000);}catch(err){copyButton.textContent = 'Copy Failed';setTimeout(function(){copyButton.textContent = 'Copy Page Name';},2000);}document.body.removeChild(textArea);if(navigator.clipboard && navigator.clipboard.writeText){navigator.clipboard.writeText(copyText).catch(function(){});}};}const closeButton = document.createElement('button');closeButton.textContent = 'Close';closeButton.style.cssText = %60 background:#6c757d;color:white;border:none;padding:10px 20px;border-radius:5px;cursor:pointer;font-size:14px;font-weight:500;%60;closeButton.onmouseover = function(){this.style.background = '#5a6268';};closeButton.onmouseout = function(){this.style.background = '#6c757d';};closeButton.onclick = function(){document.body.removeChild(overlay);};const buttonContainer = document.createElement('div');buttonContainer.style.cssText = 'margin-top:20px;';buttonContainer.appendChild(copyButton);buttonContainer.appendChild(closeButton);modal.appendChild(title);modal.appendChild(moduleLabel);modal.appendChild(moduleValue);modal.appendChild(pageLabel);modal.appendChild(pageValue);if(emptyPopupMessage){modal.appendChild(emptyPopupMessage);}modal.appendChild(autocopiedNote);modal.appendChild(buttonContainer);const overlay = document.createElement('div');overlay.style.cssText = %60 position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:999998;%60;overlay.onclick = function(){document.body.removeChild(overlay);};overlay.appendChild(modal);modal.onclick = function(e){e.stopPropagation();};document.body.appendChild(overlay);})();

 

Like & Share!

 

Cheers and have a great day!

Posted
5 comments

You are the best Tim!

Created

Works great, thanks Tim!

Created

Thanks for sharing!

Created

Perfect! Thanks!

Created

Works smoothly. Thanks for sharing.

Created