Advanced Custom Fields

Add filter for picking which acf-json file is used
Currently, if you add additional paths for ACF to load json from using acf/settings/load_json , it will use the LAST found acf field group. This means, even if a field is edited via the editor, it will still use the last path, such as from a plugin. This is described in the documentation: This filter will allow plugin and theme developers to easily register field groups, post types, taxonomies, or options pages which cannot be edited by clients. I have a different use case - we are an agency and want to have some base packages as all of our sites share a similar structure but I still need to be able to add fields to suit different clients, such as adding an additional image field in some nested field group. Currently, there is no way to change the behavior of this, it always picks the last. I propose adding a filter that would enable plugin developers to choose which file should be used for a specific field group. ` // Pick the newest version, regardless of if its in the theme or plugin folder add_filter('acf/json/pick_file', function($currentFile, $newFile, $newJson, $loadPath) { // Only modify it if its the plugins path if($currentFile && $loadPath == plugin_dir_path( __FILE__ ) . 'acf-json') { $currentJson = json_decode( file_get_contents( $json_files[ $json['key'] ] ), true ); // Compare modified dates and take newest if ( $currentJson['modified'] < $json['modified'] ) { return $newFile; } else { return $currentFile; } } return $newFile; }); ` All the code to support this would be very simple in the includes/local-json.php file: ` // __construct() add_filter( 'acf/json/pick_file', array( $this, 'pick_file' ), 10, 4 ); // scan_files() line 326 $json_files[ $json['key'] ] = apply_filters( 'acf/json/pick_file', $file, $json_files[ $json['key'] ] ?? null, $json ); // Maintain current behavior public function pick_file( $currentFile, $newFile, $newJson, $path ) { return $newFile; } ` Right now, the best you can do is choose to not include the acf-folder when doing acf/settings/load_json. This is problematic though if there are multiple field groups you want to load. Being able to filter individual files would unlock a lot of possibilities. TLDR Goal: Create new theme, importing packages via composer Use acf-json from packages Make changes via editor, save to themes acf-json folder Right now, will still use the packages acf-json, despite the theme's being newer. - Would like to use the themes json file, while allowing sync from the package should we update it. Workaround: Prepend the package's acf-folder path. This means the theme will always win, but it does unfortunately break the sync feature. Even if the package is modified and newer, it doesn't show sync available.
0
Automatically initialize WYSIWYG fields using IntersectionObserver
Admin pages with a lot of WYSIWYG fields can be significantly slow to load. That's why there is the option "Delay Initialization", that waits for the editor to be initialized as soon as the user clicks it. The related JS is from the days before IntersectionObserver was born – but it could now definitely be improved so that TinyMCE will be initialized as soon as the field enters the viewport. Here's a little function I wrote that does exactly that: /** * Attaches an intersection observer to delayed WYSIWYG fields * to enable them automatically if scrolled into view * * Uses the `ready_field` and field.addAction('load') actions * @see https://www.advancedcustomfields.com/resources/javascript-api/#actions-ready_field * @see https://www.advancedcustomfields.com/resources/javascript-api/#actions-load_field */ handleACFWysiwygField = () => { /** * Is the field delayed? */ const isDelayed = (field) => { return field.$control().hasClass("delay"); }; /** * This function will be injected into the ACF field object. * So `this` will be the field */ function observe() { if (!isDelayed(this)) { return; } const field = this; const $wrap = field.$control(); const observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { $wrap.trigger("mousedown"); observer.disconnect(); } }, { rootMargin: "300px 0px", } ); observer.observe($wrap[0]); } /** * As soon as the field is ready, prepare it * for observation */ function onReady(field) { if (!isDelayed(field)) { return; } field .$control() .find(".acf-editor-toolbar") .text("Initializing Editor ..."); field.observe = observe.bind(field); field.addAction("load", field.observe); } acf?.addAction("ready_field/type=wysiwyg", onReady); }; The function does the following things: wait for any wysiwyg field to be ready if the field is delayed wait for the field to be fully loaded ( field.addAction('load') ) patches the field with an "observe" function, that observes it and initializes the editor as soon as the field becomes within 400px of the viewport As this all can already be done using the JS API, I thought it would be worth sharing it publicly. But if the ACF support is reading this, maybe they'd consider adding the functionality to the core?
0
Load More