So, here's an example of some jQuery that hides sections of an OrderItem
detail page (Classic) based on the recordtype of the parent Order
.
<apex:page id="OrderProductDetail" standardController="OrderItem">
<!-- OrderProduct doesn't support record types so we can't have a Pre-shopify vs post-shopify layout
Use jQuery to change css on sections not relevant for Shopify orders
-->
<apex:includeScript value="{!$Resource.jQuery331Min}"/>
<script>
$j = jQuery.noConflict(true); // return globally scoped JQuery variables to first version loaded, if any
var orderProductDetailApp = {};
$j(function() { // jQuery shorthand for $(document).ready(function() .. Wait until page loads
// define the application
(function(app) { // Define anon function
// --------------------------
// init: do initializations
// --------------------------
app.init = function() {
app.hidePreShopifySections();
};
// -----------------------------------
// hidePreShopifySections: hack to hide pre-Shopify sections using css display:none
// -----------------------------------
app.hidePreShopifySections = function() {
// if parent Order recordtype.DeveloperName = 'Shopify' ....
// then apply css:none to all PageblockSections with '(pre-Shopify)' or '(Retired)' in title
// first selector: h3 w/ name attribute matching pattern
// second selector: parent - the pageblockSection header
// then repeat but with second selector .parent().next() - the pageblock section fields
var filterPattern0 = 'pre-Shopify';
var filterPattern1 = 'Retired';
// Fragility note:
// 1 Assumes that section labels contain matching strings
var orderRecordTypeDevName = '{!OrderItem.Order.RecordType.DeveloperName}';
if (orderRecordTypeDevName == 'Shopify') {
$j("h3:contains(" + filterPattern0 + ")").add("h3:contains(" +filterPattern1+")")
.parent().css('display','none'); // clear pageblocksectionHeader
$j("h3:contains(" + filterPattern0 + ")").add("h3:contains(" +filterPattern1+")")
.parent().next().css('display','none'); // clear fields
// hide the related list for custom object Order-Event_Item__c
// <div class="listRelatedObject customnotabBlock"
// ... many elements nested
// <input value="New Order Event Item ..." only clue we have to which related list to hide
// ...
// </div>
$j("input[value='New Order Event Item']")
.closest("div .listRelatedObject").css('display','none');
}
}; // end hidePreShopifySections
app.init(); // Anon function invokes its own init function
}) (orderProductDetailApp); // Execute anon function passing in an object representing our application
});
</script>
<apex:outputPanel id="detail" >
<apex:detail subject="{!OrderItem.Id}" inlineEdit="true"
onComplete="orderProductDetailApp.hidePreShopifySections();"/>
</apex:outputPanel>
</apex:page>
So, what does this example illustrate:
- It uses apex:detail so all the built-in features of
apex:detail
are available - inluding related lists, related list hover, and inline edit.
- It hides
pageblocksections
that aren't relevant based on the recordtype of the parent `Order object
- It hides a related list that also isn't relevant based on the parent Order recordtype
- No controller extension required
BUT -- it is fragile as it relies on DOM inspection for specific patterns that can be easily broken through inadvertent changes in the OOTB Lightning UI setup actions in Edit Page Layout
Approach:
- Inspect the DOM using Firefox or Chrome developer tools,
- Brush up on your jQuery selectors
- Approach the problem incrementally, getting your jQuery to work in pieces
- Comment liberally so the next admin maintaining this knows what you were doing
You can do a lot with jQuery as you have total control over DOM manipulation. You could move sections around, hide sections, hide individual fields; insert new fields (cloning DOM elements is best for this). If doing this in Classic, given that VF for classic is not likely to change, you "probably" will not be subject to SFDC changing the DOM from underneath you - YMMV.