1/** 2 * 3 * Add live SEO Validation to Yoast SEO while having custom ACF Fields. 4 * Works also with Flexible Content and Repeater Fields. 5 * https://bitbucket.org/snippets/dachcom/KKLM7/yoastseojs-acf-fields 6 * 7 * Include this Javascript ONLY in BackEnd. 8 * 9 * @author: DACHCOM.DIGITAL | Stefan Hagspiel <[email protected]> 10 * @version: 1.0.0 11 * 12 * All rights reserved. 13 * 14 */ 15(function( $ ) { 16 17 var acfPlugin; 18 19 //http://stackoverflow.com/a/965962 20 jQuery.expr[':'].parents = function(a,i,m){ 21 return jQuery(a).parents(m[3]).length < 1; 22 }; 23 24 var AcfPlugin = function() { 25 26 this.content = {}; 27 this.pluginName = 'acfPlugin'; 28 29 }; 30 31 /** 32 * Set's the field content to use in the analysis 33 * 34 * @param {Object} $el 35 */ 36 AcfPlugin.prototype.setContent = function( $el ) { 37 38 if( $el.prop('nodeName') == 'INPUT' || $el.prop('nodeName') == 'TEXTAREA' ) { 39 $el = $el.closest('div[data-name]') 40 } 41 42 var $fieldKey = $el.find('label').first().attr('for'), 43 type = $el.data('type'), 44 value = null; 45 46 switch( type) { 47 48 case 'text' : 49 value = $el.find('input').val(); 50 break; 51 case 'image' : 52 value = $el.find("img[src!='']").prop('outerHTML'); 53 break; 54 case 'gallery' : 55 value = ''; 56 $el.find("div.thumbnail > img").each(function(){ 57 value += $(this).prop('outerHTML'); 58 }); 59 break; 60 case 'wysiwyg' : 61 value = $el.find('textarea').val(); 62 break; 63 default : 64 value = null; 65 66 } 67 68 //console.log(type, $fieldKey, value); 69 70 if( value !== null ) { 71 72 this.content[ $fieldKey ] = value; 73 YoastSEO.app.pluginReloaded( this.pluginName ); 74 75 } 76 77 return true; 78 79 }; 80 81 /** 82 * Removes the field content 83 * Because ACF uses animation before element removal, we add an timeout. 84 * 85 * @param {Object} $el 86 */ 87 AcfPlugin.prototype.removeContent = function( $el ) { 88 89 var _this = this; 90 91 console.log('removeContent', this.content); 92 93 setTimeout(function() { 94 95 $.each( _this.content, function(k,v) { 96 97 if( $('label[for="'+k+'"]').filter(':parents(.clones)').length == 0 ) { 98 99 //console.log('delete label[for="'+k+'"]'); 100 delete _this.content[ k ]; 101 102 } 103 104 }); 105 106 YoastSEO.app.pluginReloaded( _this.pluginName ); 107 108 }, 600); 109 110 }; 111 112 /** 113 * Registers plugin to YoastSEO 114 */ 115 AcfPlugin.prototype.registerPlugin = function() { 116 YoastSEO.app.registerPlugin( this.pluginName, { status: 'ready' } ); 117 }; 118 119 /** 120 * Registers modifications to YoastSEO 121 */ 122 AcfPlugin.prototype.registerModifications = function() { 123 YoastSEO.app.registerModification( 'content', this.addAcfDataToContent.bind( this ), this.pluginName, 10 ); 124 }; 125 126 /** 127 * Adds ACF Data to content 128 * 129 * @param {String} content 130 * @returns {String} 131 */ 132 AcfPlugin.prototype.addAcfDataToContent = function( content ) { 133 134 if( this.content.length == 0) 135 return content; 136 137 $.each( this.content, function(k,v) { 138 content += v; 139 }); 140 141 return content; 142 143 }; 144 145 $(window).on('YoastSEO:ready', function () { 146 147 acfPlugin = new AcfPlugin(); 148 acfPlugin.registerPlugin(); 149 acfPlugin.registerModifications(); 150 151 acf.add_action('load_field', acfPlugin.setContent.bind(acfPlugin)); 152 acf.add_action('change', acfPlugin.setContent.bind(acfPlugin)); 153 acf.add_action('remove', acfPlugin.removeContent.bind(acfPlugin)); 154 155 }); 156 157}( jQuery ));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.