Server IP : 104.21.14.103 / Your IP : 3.145.37.251 Web Server : LiteSpeed System : Linux business53.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64 User : giankuin ( 1871) PHP Version : 7.4.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/giankuin/sieuthiweb.com.vn/wp-content/plugins/advanced-custom-fields-pro/assets/js/ |
Upload File : |
(function($, undefined){ /** * acf * * description * * @date 14/12/17 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ // The global acf object var acf = {}; // Set as a browser global window.acf = acf; /** @var object Data sent from PHP */ acf.data = {}; /** * get * * Gets a specific data value * * @date 14/12/17 * @since 5.6.5 * * @param string name * @return mixed */ acf.get = function( name ){ return this.data[name] || null; }; /** * has * * Returns `true` if the data exists and is not null * * @date 14/12/17 * @since 5.6.5 * * @param string name * @return boolean */ acf.has = function( name ){ return this.get(name) !== null; }; /** * set * * Sets a specific data value * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param mixed value * @return this */ acf.set = function( name, value ){ this.data[ name ] = value; return this; }; /** * uniqueId * * Returns a unique ID * * @date 9/11/17 * @since 5.6.3 * * @param string prefix Optional prefix. * @return string */ var idCounter = 0; acf.uniqueId = function(prefix){ var id = ++idCounter + ''; return prefix ? prefix + id : id; }; /** * acf.uniqueArray * * Returns a new array with only unique values * Credit: https://stackoverflow.com/questions/1960473/get-all-unique-values-in-an-array-remove-duplicates * * @date 23/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ acf.uniqueArray = function( array ){ function onlyUnique(value, index, self) { return self.indexOf(value) === index; } return array.filter( onlyUnique ); }; /** * uniqid * * Returns a unique ID (PHP version) * * @date 9/11/17 * @since 5.6.3 * @source http://locutus.io/php/misc/uniqid/ * * @param string prefix Optional prefix. * @return string */ var uniqidSeed = ''; acf.uniqid = function(prefix, moreEntropy){ // discuss at: http://locutus.io/php/uniqid/ // original by: Kevin van Zonneveld (http://kvz.io) // revised by: Kankrelune (http://www.webfaktory.info/) // note 1: Uses an internal counter (in locutus global) to avoid collision // example 1: var $id = uniqid() // example 1: var $result = $id.length === 13 // returns 1: true // example 2: var $id = uniqid('foo') // example 2: var $result = $id.length === (13 + 'foo'.length) // returns 2: true // example 3: var $id = uniqid('bar', true) // example 3: var $result = $id.length === (23 + 'bar'.length) // returns 3: true if (typeof prefix === 'undefined') { prefix = ''; } var retId; var formatSeed = function(seed, reqWidth) { seed = parseInt(seed, 10).toString(16); // to hex str if (reqWidth < seed.length) { // so long we split return seed.slice(seed.length - reqWidth); } if (reqWidth > seed.length) { // so short we pad return Array(1 + (reqWidth - seed.length)).join('0') + seed; } return seed; }; if (!uniqidSeed) { // init seed with big random int uniqidSeed = Math.floor(Math.random() * 0x75bcd15); } uniqidSeed++; retId = prefix; // start with prefix, add current milliseconds hex string retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8); retId += formatSeed(uniqidSeed, 5); // add seed hex string if (moreEntropy) { // for more entropy we add a float lower to 10 retId += (Math.random() * 10).toFixed(8).toString(); } return retId; }; /** * strReplace * * Performs a string replace * * @date 14/12/17 * @since 5.6.5 * * @param string search * @param string replace * @param string subject * @return string */ acf.strReplace = function( search, replace, subject ){ return subject.split(search).join(replace); }; /** * strCamelCase * * Converts a string into camelCase * Thanks to https://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case * * @date 14/12/17 * @since 5.6.5 * * @param string str * @return string */ acf.strCamelCase = function( str ){ var matches = str.match( /([a-zA-Z0-9]+)/g ); return matches ? matches.map(function( s, i ){ var c = s.charAt(0); return ( i === 0 ? c.toLowerCase() : c.toUpperCase() ) + s.slice(1); }).join('') : ''; }; /** * strPascalCase * * Converts a string into PascalCase * Thanks to https://stackoverflow.com/questions/1026069/how-do-i-make-the-first-letter-of-a-string-uppercase-in-javascript * * @date 14/12/17 * @since 5.6.5 * * @param string str * @return string */ acf.strPascalCase = function( str ){ var camel = acf.strCamelCase( str ); return camel.charAt(0).toUpperCase() + camel.slice(1); }; /** * acf.strSlugify * * Converts a string into a HTML class friendly slug * * @date 21/3/18 * @since 5.6.9 * * @param string str * @return string */ acf.strSlugify = function( str ){ return acf.strReplace( '_', '-', str.toLowerCase() ); }; acf.strSanitize = function( str ){ // chars (https://jsperf.com/replace-foreign-characters) var map = { "À": "A", "Á": "A", "Â": "A", "Ã": "A", "Ä": "A", "Å": "A", "Æ": "AE", "Ç": "C", "È": "E", "É": "E", "Ê": "E", "Ë": "E", "Ì": "I", "Í": "I", "Î": "I", "Ï": "I", "Ð": "D", "Ñ": "N", "Ò": "O", "Ó": "O", "Ô": "O", "Õ": "O", "Ö": "O", "Ø": "O", "Ù": "U", "Ú": "U", "Û": "U", "Ü": "U", "Ý": "Y", "ß": "s", "à": "a", "á": "a", "â": "a", "ã": "a", "ä": "a", "å": "a", "æ": "ae", "ç": "c", "è": "e", "é": "e", "ê": "e", "ë": "e", "ì": "i", "í": "i", "î": "i", "ï": "i", "ñ": "n", "ò": "o", "ó": "o", "ô": "o", "õ": "o", "ö": "o", "ø": "o", "ù": "u", "ú": "u", "û": "u", "ü": "u", "ý": "y", "ÿ": "y", "Ā": "A", "ā": "a", "Ă": "A", "ă": "a", "Ą": "A", "ą": "a", "Ć": "C", "ć": "c", "Ĉ": "C", "ĉ": "c", "Ċ": "C", "ċ": "c", "Č": "C", "č": "c", "Ď": "D", "ď": "d", "Đ": "D", "đ": "d", "Ē": "E", "ē": "e", "Ĕ": "E", "ĕ": "e", "Ė": "E", "ė": "e", "Ę": "E", "ę": "e", "Ě": "E", "ě": "e", "Ĝ": "G", "ĝ": "g", "Ğ": "G", "ğ": "g", "Ġ": "G", "ġ": "g", "Ģ": "G", "ģ": "g", "Ĥ": "H", "ĥ": "h", "Ħ": "H", "ħ": "h", "Ĩ": "I", "ĩ": "i", "Ī": "I", "ī": "i", "Ĭ": "I", "ĭ": "i", "Į": "I", "į": "i", "İ": "I", "ı": "i", "IJ": "IJ", "ij": "ij", "Ĵ": "J", "ĵ": "j", "Ķ": "K", "ķ": "k", "Ĺ": "L", "ĺ": "l", "Ļ": "L", "ļ": "l", "Ľ": "L", "ľ": "l", "Ŀ": "L", "ŀ": "l", "Ł": "l", "ł": "l", "Ń": "N", "ń": "n", "Ņ": "N", "ņ": "n", "Ň": "N", "ň": "n", "ʼn": "n", "Ō": "O", "ō": "o", "Ŏ": "O", "ŏ": "o", "Ő": "O", "ő": "o", "Œ": "OE", "œ": "oe", "Ŕ": "R", "ŕ": "r", "Ŗ": "R", "ŗ": "r", "Ř": "R", "ř": "r", "Ś": "S", "ś": "s", "Ŝ": "S", "ŝ": "s", "Ş": "S", "ş": "s", "Š": "S", "š": "s", "Ţ": "T", "ţ": "t", "Ť": "T", "ť": "t", "Ŧ": "T", "ŧ": "t", "Ũ": "U", "ũ": "u", "Ū": "U", "ū": "u", "Ŭ": "U", "ŭ": "u", "Ů": "U", "ů": "u", "Ű": "U", "ű": "u", "Ų": "U", "ų": "u", "Ŵ": "W", "ŵ": "w", "Ŷ": "Y", "ŷ": "y", "Ÿ": "Y", "Ź": "Z", "ź": "z", "Ż": "Z", "ż": "z", "Ž": "Z", "ž": "z", "ſ": "s", "ƒ": "f", "Ơ": "O", "ơ": "o", "Ư": "U", "ư": "u", "Ǎ": "A", "ǎ": "a", "Ǐ": "I", "ǐ": "i", "Ǒ": "O", "ǒ": "o", "Ǔ": "U", "ǔ": "u", "Ǖ": "U", "ǖ": "u", "Ǘ": "U", "ǘ": "u", "Ǚ": "U", "ǚ": "u", "Ǜ": "U", "ǜ": "u", "Ǻ": "A", "ǻ": "a", "Ǽ": "AE", "ǽ": "ae", "Ǿ": "O", "ǿ": "o", // extra ' ': '_', "'": '', '?': '', '/': '', '\\': '', '.': '', ',': '', '`': '', '>': '', '<': '', '"': '', '[': '', ']': '', '|': '', '{': '', '}': '', '(': '', ')': '' }; // vars var nonWord = /\W/g; var mapping = function (c) { return (map[c] !== undefined) ? map[c] : c; }; // replace str = str.replace(nonWord, mapping); // lowercase str = str.toLowerCase(); // return return str; }; /** * acf.strMatch * * Returns the number of characters that match between two strings * * @date 1/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.strMatch = function( s1, s2 ){ // vars var val = 0; var min = Math.min( s1.length, s2.length ); // loop for( var i = 0; i < min; i++ ) { if( s1[i] !== s2[i] ) { break; } val++; } // return return val; }; /** * Escapes HTML entities from a string. * * @date 08/06/2020 * @since 5.9.0 * * @param string string The input string. * @return string */ acf.strEscape = function( string ){ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return ('' + string).replace(/[&<>"']/g, function( chr ) { return htmlEscapes[ chr ]; }); }; // Tests. //console.log( acf.strEscape('Test 1') ); //console.log( acf.strEscape('Test & 1') ); //console.log( acf.strEscape('Test\'s & 1') ); //console.log( acf.strEscape('<script>js</script>') ); /** * Unescapes HTML entities from a string. * * @date 08/06/2020 * @since 5.9.0 * * @param string string The input string. * @return string */ acf.strUnescape = function( string ){ var htmlUnescapes = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'" }; return ('' + string).replace(/&|<|>|"|'/g, function( entity ) { return htmlUnescapes[ entity ]; }); }; // Tests. //console.log( acf.strUnescape( acf.strEscape('Test 1') ) ); //console.log( acf.strUnescape( acf.strEscape('Test & 1') ) ); //console.log( acf.strUnescape( acf.strEscape('Test\'s & 1') ) ); //console.log( acf.strUnescape( acf.strEscape('<script>js</script>') ) ); /** * Escapes HTML entities from a string. * * @date 08/06/2020 * @since 5.9.0 * * @param string string The input string. * @return string */ acf.escAttr = acf.strEscape; /** * Encodes <script> tags for safe HTML output. * * @date 08/06/2020 * @since 5.9.0 * * @param string string The input string. * @return string */ acf.escHtml = function( string ){ return ('' + string).replace(/<script|<\/script/g, function( html ) { return acf.strEscape( html ); }); }; // Tests. //console.log( acf.escHtml('<script>js</script>') ); //console.log( acf.escHtml( acf.strEscape('<script>js</script>') ) ); //console.log( acf.escHtml( '<script>js1</script><script>js2</script>' ) ); /** * acf.decode * * description * * @date 13/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.decode = function( string ){ return $('<textarea/>').html( string ).text(); }; /** * parseArgs * * Merges together defaults and args much like the WP wp_parse_args function * * @date 14/12/17 * @since 5.6.5 * * @param object args * @param object defaults * @return object */ acf.parseArgs = function( args, defaults ){ if( typeof args !== 'object' ) args = {}; if( typeof defaults !== 'object' ) defaults = {}; return $.extend({}, defaults, args); } /** * __ * * Retrieve the translation of $text. * * @date 16/4/18 * @since 5.6.9 * * @param string text Text to translate. * @return string Translated text. */ if( window.acfL10n == undefined ) { acfL10n = {}; } acf.__ = function( text ){ return acfL10n[ text ] || text; }; /** * _x * * Retrieve translated string with gettext context. * * @date 16/4/18 * @since 5.6.9 * * @param string text Text to translate. * @param string context Context information for the translators. * @return string Translated text. */ acf._x = function( text, context ){ return acfL10n[ text + '.' + context ] || acfL10n[ text ] || text; }; /** * _n * * Retrieve the plural or single form based on the amount. * * @date 16/4/18 * @since 5.6.9 * * @param string single Single text to translate. * @param string plural Plural text to translate. * @param int number The number to compare against. * @return string Translated text. */ acf._n = function( single, plural, number ){ if( number == 1 ) { return acf.__(single); } else { return acf.__(plural); } }; acf.isArray = function( a ){ return Array.isArray(a); }; acf.isObject = function( a ){ return ( typeof a === 'object' ); } /** * serialize * * description * * @date 24/12/17 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ var buildObject = function( obj, name, value ){ // replace [] with placeholder name = name.replace('[]', '[%%index%%]'); // vars var keys = name.match(/([^\[\]])+/g); if( !keys ) return; var length = keys.length; var ref = obj; // loop for( var i = 0; i < length; i++ ) { // vars var key = String( keys[i] ); // value if( i == length - 1 ) { // %%index%% if( key === '%%index%%' ) { ref.push( value ); // default } else { ref[ key ] = value; } // path } else { // array if( keys[i+1] === '%%index%%' ) { if( !acf.isArray(ref[ key ]) ) { ref[ key ] = []; } // object } else { if( !acf.isObject(ref[ key ]) ) { ref[ key ] = {}; } } // crawl ref = ref[ key ]; } } }; acf.serialize = function( $el, prefix ){ // vars var obj = {}; var inputs = acf.serializeArray( $el ); // prefix if( prefix !== undefined ) { // filter and modify inputs = inputs.filter(function( item ){ return item.name.indexOf(prefix) === 0; }).map(function( item ){ item.name = item.name.slice(prefix.length); return item; }); } // loop for( var i = 0; i < inputs.length; i++ ) { buildObject( obj, inputs[i].name, inputs[i].value ); } // return return obj; }; /** * acf.serializeArray * * Similar to $.serializeArray() but works with a parent wrapping element. * * @date 19/8/18 * @since 5.7.3 * * @param jQuery $el The element or form to serialize. * @return array */ acf.serializeArray = function( $el ){ return $el.find('select, textarea, input').serializeArray(); } /** * acf.serializeForAjax * * Returns an object containing name => value data ready to be encoded for Ajax. * * @date 17/12/18 * @since 5.8.0 * * @param jQUery $el The element or form to serialize. * @return object */ acf.serializeForAjax = function( $el ){ // vars var data = {}; var index = {}; // Serialize inputs. var inputs = acf.serializeArray( $el ); // Loop over inputs and build data. inputs.map(function( item ){ // Append to array. if( item.name.slice(-2) === '[]' ) { data[ item.name ] = data[ item.name ] || []; data[ item.name ].push( item.value ); // Append } else { data[ item.name ] = item.value; } }); // return return data; }; /** * addAction * * Wrapper for acf.hooks.addAction * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ /* var prefixAction = function( action ){ return 'acf_' + action; } */ acf.addAction = function( action, callback, priority, context ){ //action = prefixAction(action); acf.hooks.addAction.apply(this, arguments); return this; }; /** * removeAction * * Wrapper for acf.hooks.removeAction * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.removeAction = function( action, callback ){ //action = prefixAction(action); acf.hooks.removeAction.apply(this, arguments); return this; }; /** * doAction * * Wrapper for acf.hooks.doAction * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ var actionHistory = {}; //var currentAction = false; acf.doAction = function( action ){ //action = prefixAction(action); //currentAction = action; actionHistory[ action ] = 1; acf.hooks.doAction.apply(this, arguments); actionHistory[ action ] = 0; return this; }; /** * doingAction * * Return true if doing action * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.doingAction = function( action ){ //action = prefixAction(action); return (actionHistory[ action ] === 1); }; /** * didAction * * Wrapper for acf.hooks.doAction * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.didAction = function( action ){ //action = prefixAction(action); return (actionHistory[ action ] !== undefined); }; /** * currentAction * * Wrapper for acf.hooks.doAction * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.currentAction = function(){ for( var k in actionHistory ) { if( actionHistory[k] ) { return k; } } return false; }; /** * addFilter * * Wrapper for acf.hooks.addFilter * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.addFilter = function( action ){ //action = prefixAction(action); acf.hooks.addFilter.apply(this, arguments); return this; }; /** * removeFilter * * Wrapper for acf.hooks.removeFilter * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.removeFilter = function( action ){ //action = prefixAction(action); acf.hooks.removeFilter.apply(this, arguments); return this; }; /** * applyFilters * * Wrapper for acf.hooks.applyFilters * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return this */ acf.applyFilters = function( action ){ //action = prefixAction(action); return acf.hooks.applyFilters.apply(this, arguments); }; /** * getArgs * * description * * @date 15/12/17 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.arrayArgs = function( args ){ return Array.prototype.slice.call( args ); }; /** * extendArgs * * description * * @date 15/12/17 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ /* acf.extendArgs = function( ){ var args = Array.prototype.slice.call( arguments ); var realArgs = args.shift(); Array.prototype.push.call(arguments, 'bar') return Array.prototype.push.apply( args, arguments ); }; */ // Preferences // - use try/catch to avoid JS error if cookies are disabled on front-end form try { var preferences = JSON.parse(localStorage.getItem('acf')) || {}; } catch(e) { var preferences = {}; } /** * getPreferenceName * * Gets the true preference name. * Converts "this.thing" to "thing-123" if editing post 123. * * @date 11/11/17 * @since 5.6.5 * * @param string name * @return string */ var getPreferenceName = function( name ){ if( name.substr(0, 5) === 'this.' ) { name = name.substr(5) + '-' + acf.get('post_id'); } return name; }; /** * acf.getPreference * * Gets a preference setting or null if not set. * * @date 11/11/17 * @since 5.6.5 * * @param string name * @return mixed */ acf.getPreference = function( name ){ name = getPreferenceName( name ); return preferences[ name ] || null; } /** * acf.setPreference * * Sets a preference setting. * * @date 11/11/17 * @since 5.6.5 * * @param string name * @param mixed value * @return n/a */ acf.setPreference = function( name, value ){ name = getPreferenceName( name ); if( value === null ) { delete preferences[ name ]; } else { preferences[ name ] = value; } localStorage.setItem('acf', JSON.stringify(preferences)); } /** * acf.removePreference * * Removes a preference setting. * * @date 11/11/17 * @since 5.6.5 * * @param string name * @return n/a */ acf.removePreference = function( name ){ acf.setPreference(name, null); }; /** * remove * * Removes an element with fade effect * * @date 1/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.remove = function( props ){ // allow jQuery if( props instanceof jQuery ) { props = { target: props }; } // defaults props = acf.parseArgs(props, { target: false, endHeight: 0, complete: function(){} }); // action acf.doAction('remove', props.target); // tr if( props.target.is('tr') ) { removeTr( props ); // div } else { removeDiv( props ); } }; /** * removeDiv * * description * * @date 16/2/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ var removeDiv = function( props ){ // vars var $el = props.target; var height = $el.height(); var width = $el.width(); var margin = $el.css('margin'); var outerHeight = $el.outerHeight(true); var style = $el.attr('style') + ''; // needed to copy // wrap $el.wrap('<div class="acf-temp-remove" style="height:' + outerHeight + 'px"></div>'); var $wrap = $el.parent(); // set pos $el.css({ height: height, width: width, margin: margin, position: 'absolute' }); // fade wrap setTimeout(function(){ $wrap.css({ opacity: 0, height: props.endHeight }); }, 50); // remove setTimeout(function(){ $el.attr('style', style); $wrap.remove(); props.complete(); }, 301); }; /** * removeTr * * description * * @date 16/2/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ var removeTr = function( props ){ // vars var $tr = props.target; var height = $tr.height(); var children = $tr.children().length; // create dummy td var $td = $('<td class="acf-temp-remove" style="padding:0; height:' + height + 'px" colspan="' + children + '"></td>'); // fade away tr $tr.addClass('acf-remove-element'); // update HTML after fade animation setTimeout(function(){ $tr.html( $td ); }, 251); // allow .acf-temp-remove to exist before changing CSS setTimeout(function(){ // remove class $tr.removeClass('acf-remove-element'); // collapse $td.css({ height: props.endHeight }); }, 300); // remove setTimeout(function(){ $tr.remove(); props.complete(); }, 451); }; /** * duplicate * * description * * @date 3/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.duplicate = function( args ){ // allow jQuery if( args instanceof jQuery ) { args = { target: args }; } // defaults args = acf.parseArgs(args, { target: false, search: '', replace: '', rename: true, before: function( $el ){}, after: function( $el, $el2 ){}, append: function( $el, $el2 ){ $el.after( $el2 ); } }); // compatibility args.target = args.target || args.$el; // vars var $el = args.target; // search args.search = args.search || $el.attr('data-id'); args.replace = args.replace || acf.uniqid(); // before // - allow acf to modify DOM // - fixes bug where select field option is not selected args.before( $el ); acf.doAction('before_duplicate', $el); // clone var $el2 = $el.clone(); // rename if( args.rename ) { acf.rename({ target: $el2, search: args.search, replace: args.replace, replacer: ( typeof args.rename === 'function' ? args.rename : null ) }); } // remove classes $el2.removeClass('acf-clone'); $el2.find('.ui-sortable').removeClass('ui-sortable'); // after // - allow acf to modify DOM args.after( $el, $el2 ); acf.doAction('after_duplicate', $el, $el2 ); // append args.append( $el, $el2 ); /** * Fires after an element has been duplicated and appended to the DOM. * * @date 30/10/19 * @since 5.8.7 * * @param jQuery $el The original element. * @param jQuery $el2 The duplicated element. */ acf.doAction('duplicate', $el, $el2 ); // append acf.doAction('append', $el2); // return return $el2; }; /** * rename * * description * * @date 7/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.rename = function( args ){ // Allow jQuery param. if( args instanceof jQuery ) { args = { target: args }; } // Apply default args. args = acf.parseArgs(args, { target: false, destructive: false, search: '', replace: '', replacer: null }); // Extract args. var $el = args.target; // Provide backup for empty args. if( !args.search ) { args.search = $el.attr('data-id'); } if( !args.replace ) { args.replace = acf.uniqid('acf'); } if( !args.replacer ) { args.replacer = function( name, value, search, replace ){ return value.replace( search, replace ); }; } // Callback function for jQuery replacing. var withReplacer = function( name ){ return function( i, value ){ return args.replacer( name, value, args.search, args.replace ); } }; // Destructive Replace. if( args.destructive ) { var html = acf.strReplace( args.search, args.replace, $el.outerHTML() ); $el.replaceWith( html ); // Standard Replace. } else { $el.attr('data-id', args.replace); $el.find('[id*="' + args.search + '"]').attr('id', withReplacer('id')); $el.find('[for*="' + args.search + '"]').attr('for', withReplacer('for')); $el.find('[name*="' + args.search + '"]').attr('name', withReplacer('name')); } // return return $el; }; /** * acf.prepareForAjax * * description * * @date 4/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.prepareForAjax = function( data ){ // required data.nonce = acf.get('nonce'); data.post_id = acf.get('post_id'); // language if( acf.has('language') ) { data.lang = acf.get('language'); } // filter for 3rd party customization data = acf.applyFilters('prepare_for_ajax', data); // return return data; }; /** * acf.startButtonLoading * * description * * @date 5/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.startButtonLoading = function( $el ){ $el.prop('disabled', true); $el.after(' <i class="acf-loading"></i>'); } acf.stopButtonLoading = function( $el ){ $el.prop('disabled', false); $el.next('.acf-loading').remove(); } /** * acf.showLoading * * description * * @date 12/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.showLoading = function( $el ){ $el.append('<div class="acf-loading-overlay"><i class="acf-loading"></i></div>'); }; acf.hideLoading = function( $el ){ $el.children('.acf-loading-overlay').remove(); }; /** * acf.updateUserSetting * * description * * @date 5/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.updateUserSetting = function( name, value ){ var ajaxData = { action: 'acf/ajax/user_setting', name: name, value: value }; $.ajax({ url: acf.get('ajaxurl'), data: acf.prepareForAjax(ajaxData), type: 'post', dataType: 'html' }); }; /** * acf.val * * description * * @date 8/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.val = function( $input, value, silent ){ // vars var prevValue = $input.val(); // bail if no change if( value === prevValue ) { return false } // update value $input.val( value ); // prevent select elements displaying blank value if option doesn't exist if( $input.is('select') && $input.val() === null ) { $input.val( prevValue ); return false; } // update with trigger if( silent !== true ) { $input.trigger('change'); } // return return true; }; /** * acf.show * * description * * @date 9/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.show = function( $el, lockKey ){ // unlock if( lockKey ) { acf.unlock($el, 'hidden', lockKey); } // bail early if $el is still locked if( acf.isLocked($el, 'hidden') ) { //console.log( 'still locked', getLocks( $el, 'hidden' )); return false; } // $el is hidden, remove class and return true due to change in visibility if( $el.hasClass('acf-hidden') ) { $el.removeClass('acf-hidden'); return true; // $el is visible, return false due to no change in visibility } else { return false; } }; /** * acf.hide * * description * * @date 9/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.hide = function( $el, lockKey ){ // lock if( lockKey ) { acf.lock($el, 'hidden', lockKey); } // $el is hidden, return false due to no change in visibility if( $el.hasClass('acf-hidden') ) { return false; // $el is visible, add class and return true due to change in visibility } else { $el.addClass('acf-hidden'); return true; } }; /** * acf.isHidden * * description * * @date 9/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.isHidden = function( $el ){ return $el.hasClass('acf-hidden'); }; /** * acf.isVisible * * description * * @date 9/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.isVisible = function( $el ){ return !acf.isHidden( $el ); }; /** * enable * * description * * @date 12/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ var enable = function( $el, lockKey ){ // check class. Allow .acf-disabled to overrule all JS if( $el.hasClass('acf-disabled') ) { return false; } // unlock if( lockKey ) { acf.unlock($el, 'disabled', lockKey); } // bail early if $el is still locked if( acf.isLocked($el, 'disabled') ) { return false; } // $el is disabled, remove prop and return true due to change if( $el.prop('disabled') ) { $el.prop('disabled', false); return true; // $el is enabled, return false due to no change } else { return false; } }; /** * acf.enable * * description * * @date 9/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.enable = function( $el, lockKey ){ // enable single input if( $el.attr('name') ) { return enable( $el, lockKey ); } // find and enable child inputs // return true if any inputs have changed var results = false; $el.find('[name]').each(function(){ var result = enable( $(this), lockKey ); if( result ) { results = true; } }); return results; }; /** * disable * * description * * @date 12/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ var disable = function( $el, lockKey ){ // lock if( lockKey ) { acf.lock($el, 'disabled', lockKey); } // $el is disabled, return false due to no change if( $el.prop('disabled') ) { return false; // $el is enabled, add prop and return true due to change } else { $el.prop('disabled', true); return true; } }; /** * acf.disable * * description * * @date 9/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.disable = function( $el, lockKey ){ // disable single input if( $el.attr('name') ) { return disable( $el, lockKey ); } // find and enable child inputs // return true if any inputs have changed var results = false; $el.find('[name]').each(function(){ var result = disable( $(this), lockKey ); if( result ) { results = true; } }); return results; }; /** * acf.isset * * description * * @date 10/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.isset = function( obj /*, level1, level2, ... */ ) { for( var i = 1; i < arguments.length; i++ ) { if( !obj || !obj.hasOwnProperty(arguments[i]) ) { return false; } obj = obj[ arguments[i] ]; } return true; }; /** * acf.isget * * description * * @date 10/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.isget = function( obj /*, level1, level2, ... */ ) { for( var i = 1; i < arguments.length; i++ ) { if( !obj || !obj.hasOwnProperty(arguments[i]) ) { return null; } obj = obj[ arguments[i] ]; } return obj; }; /** * acf.getFileInputData * * description * * @date 10/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.getFileInputData = function( $input, callback ){ // vars var value = $input.val(); // bail early if no value if( !value ) { return false; } // data var data = { url: value }; // modern browsers var file = acf.isget( $input[0], 'files', 0); if( file ){ // update data data.size = file.size; data.type = file.type; // image if( file.type.indexOf('image') > -1 ) { // vars var windowURL = window.URL || window.webkitURL; var img = new Image(); img.onload = function() { // update data.width = this.width; data.height = this.height; callback( data ); }; img.src = windowURL.createObjectURL( file ); } else { callback( data ); } } else { callback( data ); } }; /** * acf.isAjaxSuccess * * description * * @date 18/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.isAjaxSuccess = function( json ){ return ( json && json.success ); }; /** * acf.getAjaxMessage * * description * * @date 18/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.getAjaxMessage = function( json ){ return acf.isget( json, 'data', 'message' ); }; /** * acf.getAjaxError * * description * * @date 18/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.getAjaxError = function( json ){ return acf.isget( json, 'data', 'error' ); }; /** * Returns the error message from an XHR object. * * @date 17/3/20 * @since 5.8.9 * * @param object xhr The XHR object. * @return (string) */ acf.getXhrError = function( xhr ){ if( xhr.responseJSON && xhr.responseJSON.message ) { return xhr.responseJSON.message; } else if( xhr.statusText ) { return xhr.statusText; } return ""; }; /** * acf.renderSelect * * Renders the innter html for a select field. * * @date 19/2/18 * @since 5.6.9 * * @param jQuery $select The select element. * @param array choices An array of choices. * @return void */ acf.renderSelect = function( $select, choices ){ // vars var value = $select.val(); var values = []; // callback var crawl = function( items ){ // vars var itemsHtml = ''; // loop items.map(function( item ){ // vars var text = item.text || item.label || ''; var id = item.id || item.value || ''; // append values.push(id); // optgroup if( item.children ) { itemsHtml += '<optgroup label="' + acf.escAttr(text) + '">' + crawl( item.children ) + '</optgroup>'; // option } else { itemsHtml += '<option value="' + acf.escAttr(id) + '"' + (item.disabled ? ' disabled="disabled"' : '') + '>' + acf.strEscape(text) + '</option>'; } }); // return return itemsHtml; }; // update HTML $select.html( crawl(choices) ); // update value if( values.indexOf(value) > -1 ){ $select.val( value ); } // return selected value return $select.val(); }; /** * acf.lock * * Creates a "lock" on an element for a given type and key * * @date 22/2/18 * @since 5.6.9 * * @param jQuery $el The element to lock. * @param string type The type of lock such as "condition" or "visibility". * @param string key The key that will be used to unlock. * @return void */ var getLocks = function( $el, type ){ return $el.data('acf-lock-'+type) || []; }; var setLocks = function( $el, type, locks ){ $el.data('acf-lock-'+type, locks); } acf.lock = function( $el, type, key ){ var locks = getLocks( $el, type ); var i = locks.indexOf(key); if( i < 0 ) { locks.push( key ); setLocks( $el, type, locks ); } }; /** * acf.unlock * * Unlocks a "lock" on an element for a given type and key * * @date 22/2/18 * @since 5.6.9 * * @param jQuery $el The element to lock. * @param string type The type of lock such as "condition" or "visibility". * @param string key The key that will be used to unlock. * @return void */ acf.unlock = function( $el, type, key ){ var locks = getLocks( $el, type ); var i = locks.indexOf(key); if( i > -1 ) { locks.splice(i, 1); setLocks( $el, type, locks ); } // return true if is unlocked (no locks) return (locks.length === 0); }; /** * acf.isLocked * * Returns true if a lock exists for a given type * * @date 22/2/18 * @since 5.6.9 * * @param jQuery $el The element to lock. * @param string type The type of lock such as "condition" or "visibility". * @return void */ acf.isLocked = function( $el, type ){ return ( getLocks( $el, type ).length > 0 ); }; /** * acf.isGutenberg * * Returns true if the Gutenberg editor is being used. * * @date 14/11/18 * @since 5.8.0 * * @param vois * @return bool */ acf.isGutenberg = function(){ return !!( window.wp && wp.data && wp.data.select && wp.data.select( 'core/editor' ) ); }; /** * acf.objectToArray * * Returns an array of items from the given object. * * @date 20/11/18 * @since 5.8.0 * * @param object obj The object of items. * @return array */ acf.objectToArray = function( obj ){ return Object.keys( obj ).map(function( key ){ return obj[key]; }); }; /** * acf.debounce * * Returns a debounced version of the passed function which will postpone its execution until after `wait` milliseconds have elapsed since the last time it was invoked. * * @date 28/8/19 * @since 5.8.1 * * @param function callback The callback function. * @return int wait The number of milliseconds to wait. */ acf.debounce = function( callback, wait ){ var timeout; return function(){ var context = this; var args = arguments; var later = function(){ callback.apply( context, args ); }; clearTimeout( timeout ); timeout = setTimeout( later, wait ); }; }; /** * acf.throttle * * Returns a throttled version of the passed function which will allow only one execution per `limit` time period. * * @date 28/8/19 * @since 5.8.1 * * @param function callback The callback function. * @return int wait The number of milliseconds to wait. */ acf.throttle = function( callback, limit ){ var busy = false; return function(){ if( busy ) return; busy = true; setTimeout(function(){ busy = false; }, limit); callback.apply( this, arguments ); }; }; /** * acf.isInView * * Returns true if the given element is in view. * * @date 29/8/19 * @since 5.8.1 * * @param elem el The dom element to inspect. * @return bool */ acf.isInView = function( el ){ if( el instanceof jQuery ) { el = el[0]; } var rect = el.getBoundingClientRect(); return ( rect.top !== rect.bottom && rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }; /** * acf.onceInView * * Watches for a dom element to become visible in the browser and then excecutes the passed callback. * * @date 28/8/19 * @since 5.8.1 * * @param dom el The dom element to inspect. * @param function callback The callback function. */ acf.onceInView = (function() { // Define list. var items = []; var id = 0; // Define check function. var check = function() { items.forEach(function( item ){ if( acf.isInView(item.el) ) { item.callback.apply( this ); pop( item.id ); } }); }; // And create a debounced version. var debounced = acf.debounce( check, 300 ); // Define add function. var push = function( el, callback ) { // Add event listener. if( !items.length ) { $(window).on( 'scroll resize', debounced ).on( 'acfrefresh orientationchange', check ); } // Append to list. items.push({ id: id++, el: el, callback: callback }); } // Define remove function. var pop = function( id ) { // Remove from list. items = items.filter(function(item) { return (item.id !== id); }); // Clean up listener. if( !items.length ) { $(window).off( 'scroll resize', debounced ).off( 'acfrefresh orientationchange', check ); } } // Define returned function. return function( el, callback ){ // Allow jQuery object. if( el instanceof jQuery ) el = el[0]; // Execute callback if already in view or add to watch list. if( acf.isInView(el) ) { callback.apply( this ); } else { push( el, callback ); } } })(); /** * acf.once * * Creates a function that is restricted to invoking `func` once. * * @date 2/9/19 * @since 5.8.1 * * @param function func The function to restrict. * @return function */ acf.once = function( func ){ var i = 0; return function(){ if( i++ > 0 ) { return (func = undefined); } return func.apply(this, arguments); } } /** * Focuses attention to a specific element. * * @date 05/05/2020 * @since 5.9.0 * * @param jQuery $el The jQuery element to focus. * @return void */ acf.focusAttention = function( $el ){ var wait = 1000; // Apply class to focus attention. $el.addClass( 'acf-attention -focused' ); // Scroll to element if needed. var scrollTime = 500; if( !acf.isInView( $el ) ) { $( 'body, html' ).animate({ scrollTop: $el.offset().top - ( $(window).height() / 2 ) }, scrollTime); wait += scrollTime; } // Remove class after $wait amount of time. var fadeTime = 250; setTimeout(function(){ $el.removeClass( '-focused' ); setTimeout(function(){ $el.removeClass( 'acf-attention' ); }, fadeTime); }, wait); }; /** * Description * * @date 05/05/2020 * @since 5.9.0 * * @param type Var Description. * @return type Description. */ acf.onFocus = function( $el, callback ){ // Only run once per element. // if( $el.data('acf.onFocus') ) { // return false; // } // Vars. var ignoreBlur = false; var focus = false; // Functions. var onFocus = function(){ ignoreBlur = true; setTimeout(function(){ ignoreBlur = false; }, 1); setFocus( true ); }; var onBlur = function(){ if( !ignoreBlur ) { setFocus( false ); } }; var addEvents = function(){ $(document).on('click', onBlur); //$el.on('acfBlur', onBlur); $el.on('blur', 'input, select, textarea', onBlur); }; var removeEvents = function(){ $(document).off('click', onBlur); //$el.off('acfBlur', onBlur); $el.off('blur', 'input, select, textarea', onBlur); }; var setFocus = function( value ){ if( focus === value ) { return; } if( value ) { addEvents(); } else { removeEvents(); } focus = value; callback( value ); }; // Add events and set data. $el.on('click', onFocus); //$el.on('acfFocus', onFocus); $el.on('focus', 'input, select, textarea', onFocus); //$el.data('acf.onFocus', true); }; /* * exists * * This function will return true if a jQuery selection exists * * @type function * @date 8/09/2014 * @since 5.0.0 * * @param n/a * @return (boolean) */ $.fn.exists = function() { return $(this).length>0; }; /* * outerHTML * * This function will return a string containing the HTML of the selected element * * @type function * @date 19/11/2013 * @since 5.0.0 * * @param $.fn * @return (string) */ $.fn.outerHTML = function() { return $(this).get(0).outerHTML; }; /* * indexOf * * This function will provide compatibility for ie8 * * @type function * @date 5/3/17 * @since 5.5.10 * * @param n/a * @return n/a */ if( !Array.prototype.indexOf ) { Array.prototype.indexOf = function(val) { return $.inArray(val, this); }; } /** * Triggers a "refresh" action used by various Components to redraw the DOM. * * @date 26/05/2020 * @since 5.9.0 * * @param void * @return void */ acf.refresh = acf.debounce(function(){ $( window ).trigger('acfrefresh'); acf.doAction('refresh'); }, 0); // Set up actions from events $(document).ready(function(){ acf.doAction('ready'); }); $(window).on('load', function(){ acf.doAction('load'); }); $(window).on('beforeunload', function(){ acf.doAction('unload'); }); $(window).on('resize', function(){ acf.doAction('resize'); }); $(document).on('sortstart', function( event, ui ) { acf.doAction('sortstart', ui.item, ui.placeholder); }); $(document).on('sortstop', function( event, ui ) { acf.doAction('sortstop', ui.item, ui.placeholder); }); })(jQuery); ( function( window, undefined ) { "use strict"; /** * Handles managing all events for whatever you plug it into. Priorities for hooks are based on lowest to highest in * that, lowest priority hooks are fired first. */ var EventManager = function() { /** * Maintain a reference to the object scope so our public methods never get confusing. */ var MethodsAvailable = { removeFilter : removeFilter, applyFilters : applyFilters, addFilter : addFilter, removeAction : removeAction, doAction : doAction, addAction : addAction, storage : getStorage }; /** * Contains the hooks that get registered with this EventManager. The array for storage utilizes a "flat" * object literal such that looking up the hook utilizes the native object literal hash. */ var STORAGE = { actions : {}, filters : {} }; function getStorage() { return STORAGE; }; /** * Adds an action to the event manager. * * @param action Must contain namespace.identifier * @param callback Must be a valid callback function before this action is added * @param [priority=10] Used to control when the function is executed in relation to other callbacks bound to the same hook * @param [context] Supply a value to be used for this */ function addAction( action, callback, priority, context ) { if( typeof action === 'string' && typeof callback === 'function' ) { priority = parseInt( ( priority || 10 ), 10 ); _addHook( 'actions', action, callback, priority, context ); } return MethodsAvailable; } /** * Performs an action if it exists. You can pass as many arguments as you want to this function; the only rule is * that the first argument must always be the action. */ function doAction( /* action, arg1, arg2, ... */ ) { var args = Array.prototype.slice.call( arguments ); var action = args.shift(); if( typeof action === 'string' ) { _runHook( 'actions', action, args ); } return MethodsAvailable; } /** * Removes the specified action if it contains a namespace.identifier & exists. * * @param action The action to remove * @param [callback] Callback function to remove */ function removeAction( action, callback ) { if( typeof action === 'string' ) { _removeHook( 'actions', action, callback ); } return MethodsAvailable; } /** * Adds a filter to the event manager. * * @param filter Must contain namespace.identifier * @param callback Must be a valid callback function before this action is added * @param [priority=10] Used to control when the function is executed in relation to other callbacks bound to the same hook * @param [context] Supply a value to be used for this */ function addFilter( filter, callback, priority, context ) { if( typeof filter === 'string' && typeof callback === 'function' ) { priority = parseInt( ( priority || 10 ), 10 ); _addHook( 'filters', filter, callback, priority, context ); } return MethodsAvailable; } /** * Performs a filter if it exists. You should only ever pass 1 argument to be filtered. The only rule is that * the first argument must always be the filter. */ function applyFilters( /* filter, filtered arg, arg2, ... */ ) { var args = Array.prototype.slice.call( arguments ); var filter = args.shift(); if( typeof filter === 'string' ) { return _runHook( 'filters', filter, args ); } return MethodsAvailable; } /** * Removes the specified filter if it contains a namespace.identifier & exists. * * @param filter The action to remove * @param [callback] Callback function to remove */ function removeFilter( filter, callback ) { if( typeof filter === 'string') { _removeHook( 'filters', filter, callback ); } return MethodsAvailable; } /** * Removes the specified hook by resetting the value of it. * * @param type Type of hook, either 'actions' or 'filters' * @param hook The hook (namespace.identifier) to remove * @private */ function _removeHook( type, hook, callback, context ) { if ( !STORAGE[ type ][ hook ] ) { return; } if ( !callback ) { STORAGE[ type ][ hook ] = []; } else { var handlers = STORAGE[ type ][ hook ]; var i; if ( !context ) { for ( i = handlers.length; i--; ) { if ( handlers[i].callback === callback ) { handlers.splice( i, 1 ); } } } else { for ( i = handlers.length; i--; ) { var handler = handlers[i]; if ( handler.callback === callback && handler.context === context) { handlers.splice( i, 1 ); } } } } } /** * Adds the hook to the appropriate storage container * * @param type 'actions' or 'filters' * @param hook The hook (namespace.identifier) to add to our event manager * @param callback The function that will be called when the hook is executed. * @param priority The priority of this hook. Must be an integer. * @param [context] A value to be used for this * @private */ function _addHook( type, hook, callback, priority, context ) { var hookObject = { callback : callback, priority : priority, context : context }; // Utilize 'prop itself' : http://jsperf.com/hasownproperty-vs-in-vs-undefined/19 var hooks = STORAGE[ type ][ hook ]; if( hooks ) { hooks.push( hookObject ); hooks = _hookInsertSort( hooks ); } else { hooks = [ hookObject ]; } STORAGE[ type ][ hook ] = hooks; } /** * Use an insert sort for keeping our hooks organized based on priority. This function is ridiculously faster * than bubble sort, etc: http://jsperf.com/javascript-sort * * @param hooks The custom array containing all of the appropriate hooks to perform an insert sort on. * @private */ function _hookInsertSort( hooks ) { var tmpHook, j, prevHook; for( var i = 1, len = hooks.length; i < len; i++ ) { tmpHook = hooks[ i ]; j = i; while( ( prevHook = hooks[ j - 1 ] ) && prevHook.priority > tmpHook.priority ) { hooks[ j ] = hooks[ j - 1 ]; --j; } hooks[ j ] = tmpHook; } return hooks; } /** * Runs the specified hook. If it is an action, the value is not modified but if it is a filter, it is. * * @param type 'actions' or 'filters' * @param hook The hook ( namespace.identifier ) to be ran. * @param args Arguments to pass to the action/filter. If it's a filter, args is actually a single parameter. * @private */ function _runHook( type, hook, args ) { var handlers = STORAGE[ type ][ hook ]; if ( !handlers ) { return (type === 'filters') ? args[0] : false; } var i = 0, len = handlers.length; if ( type === 'filters' ) { for ( ; i < len; i++ ) { args[ 0 ] = handlers[ i ].callback.apply( handlers[ i ].context, args ); } } else { for ( ; i < len; i++ ) { handlers[ i ].callback.apply( handlers[ i ].context, args ); } } return ( type === 'filters' ) ? args[ 0 ] : true; } // return all of the publicly available methods return MethodsAvailable; }; // instantiate acf.hooks = new EventManager(); } )( window ); (function($, undefined){ // Cached regex to split keys for `addEvent`. var delegateEventSplitter = /^(\S+)\s*(.*)$/; /** * extend * * Helper function to correctly set up the prototype chain for subclasses * Heavily inspired by backbone.js * * @date 14/12/17 * @since 5.6.5 * * @param object protoProps New properties for this object. * @return function. */ var extend = function( protoProps ) { // vars var Parent = this; var Child; // The constructor function for the new subclass is either defined by you // (the "constructor" property in your `extend` definition), or defaulted // by us to simply call the parent constructor. if( protoProps && protoProps.hasOwnProperty('constructor') ) { Child = protoProps.constructor; } else { Child = function(){ return Parent.apply(this, arguments); }; } // Add static properties to the constructor function, if supplied. $.extend(Child, Parent); // Set the prototype chain to inherit from `parent`, without calling // `parent`'s constructor function and add the prototype properties. Child.prototype = Object.create(Parent.prototype); $.extend(Child.prototype, protoProps); Child.prototype.constructor = Child; // Set a convenience property in case the parent's prototype is needed later. //Child.prototype.__parent__ = Parent.prototype; // return return Child; }; /** * Model * * Base class for all inheritence * * @date 14/12/17 * @since 5.6.5 * * @param object props * @return function. */ var Model = acf.Model = function(){ // generate uique client id this.cid = acf.uniqueId('acf'); // set vars to avoid modifying prototype this.data = $.extend(true, {}, this.data); // pass props to setup function this.setup.apply(this, arguments); // store on element (allow this.setup to create this.$el) if( this.$el && !this.$el.data('acf') ) { this.$el.data('acf', this); } // initialize var initialize = function(){ this.initialize(); this.addEvents(); this.addActions(); this.addFilters(); }; // initialize on action if( this.wait && !acf.didAction(this.wait) ) { this.addAction(this.wait, initialize); // initialize now } else { initialize.apply(this); } }; // Attach all inheritable methods to the Model prototype. $.extend(Model.prototype, { // Unique model id id: '', // Unique client id cid: '', // jQuery element $el: null, // Data specific to this instance data: {}, // toggle used when changing data busy: false, changed: false, // Setup events hooks events: {}, actions: {}, filters: {}, // class used to avoid nested event triggers eventScope: '', // action to wait until initialize wait: false, // action priority default priority: 10, /** * get * * Gets a specific data value * * @date 14/12/17 * @since 5.6.5 * * @param string name * @return mixed */ get: function( name ) { return this.data[name]; }, /** * has * * Returns `true` if the data exists and is not null * * @date 14/12/17 * @since 5.6.5 * * @param string name * @return boolean */ has: function( name ) { return this.get(name) != null; }, /** * set * * Sets a specific data value * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param mixed value * @return this */ set: function( name, value, silent ) { // bail if unchanged var prevValue = this.get(name); if( prevValue == value ) { return this; } // set data this.data[ name ] = value; // trigger events if( !silent ) { this.changed = true; this.trigger('changed:' + name, [value, prevValue]); this.trigger('changed', [name, value, prevValue]); } // return return this; }, /** * inherit * * Inherits the data from a jQuery element * * @date 14/12/17 * @since 5.6.5 * * @param jQuery $el * @return this */ inherit: function( data ){ // allow jQuery if( data instanceof jQuery ) { data = data.data(); } // extend $.extend(this.data, data); // return return this; }, /** * prop * * mimics the jQuery prop function * * @date 4/6/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ prop: function(){ return this.$el.prop.apply(this.$el, arguments); }, /** * setup * * Run during constructor function * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return n/a */ setup: function( props ){ $.extend(this, props); }, /** * initialize * * Also run during constructor function * * @date 14/12/17 * @since 5.6.5 * * @param n/a * @return n/a */ initialize: function(){}, /** * addElements * * Adds multiple jQuery elements to this object * * @date 9/5/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ addElements: function( elements ){ elements = elements || this.elements || null; if( !elements || !Object.keys(elements).length ) return false; for( var i in elements ) { this.addElement( i, elements[i] ); } }, /** * addElement * * description * * @date 9/5/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ addElement: function( name, selector){ this[ '$' + name ] = this.$( selector ); }, /** * addEvents * * Adds multiple event handlers * * @date 14/12/17 * @since 5.6.5 * * @param object events {event1 : callback, event2 : callback, etc } * @return n/a */ addEvents: function( events ){ events = events || this.events || null; if( !events ) return false; for( var key in events ) { var match = key.match(delegateEventSplitter); this.on(match[1], match[2], events[key]); } }, /** * removeEvents * * Removes multiple event handlers * * @date 14/12/17 * @since 5.6.5 * * @param object events {event1 : callback, event2 : callback, etc } * @return n/a */ removeEvents: function( events ){ events = events || this.events || null; if( !events ) return false; for( var key in events ) { var match = key.match(delegateEventSplitter); this.off(match[1], match[2], events[key]); } }, /** * getEventTarget * * Returns a jQUery element to tigger an event on * * @date 5/6/18 * @since 5.6.9 * * @param jQuery $el The default jQuery element. Optional. * @param string event The event name. Optional. * @return jQuery */ getEventTarget: function( $el, event ){ return $el || this.$el || $(document); }, /** * validateEvent * * Returns true if the event target's closest $el is the same as this.$el * Requires both this.el and this.$el to be defined * * @date 5/6/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ validateEvent: function( e ){ if( this.eventScope ) { return $( e.target ).closest( this.eventScope ).is( this.$el ); } else { return true; } }, /** * proxyEvent * * Returns a new event callback function scoped to this model * * @date 29/3/18 * @since 5.6.9 * * @param function callback * @return function */ proxyEvent: function( callback ){ return this.proxy(function(e){ // validate if( !this.validateEvent(e) ) { return; } // construct args var args = acf.arrayArgs( arguments ); var extraArgs = args.slice(1); var eventArgs = [ e, $(e.currentTarget) ].concat( extraArgs ); // callback callback.apply(this, eventArgs); }); }, /** * on * * Adds an event handler similar to jQuery * Uses the instance 'cid' to namespace event * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ on: function( a1, a2, a3, a4 ){ // vars var $el, event, selector, callback, args; // find args if( a1 instanceof jQuery ) { // 1. args( $el, event, selector, callback ) if( a4 ) { $el = a1; event = a2; selector = a3; callback = a4; // 2. args( $el, event, callback ) } else { $el = a1; event = a2; callback = a3; } } else { // 3. args( event, selector, callback ) if( a3 ) { event = a1; selector = a2; callback = a3; // 4. args( event, callback ) } else { event = a1; callback = a2; } } // element $el = this.getEventTarget( $el ); // modify callback if( typeof callback === 'string' ) { callback = this.proxyEvent( this[callback] ); } // modify event event = event + '.' + this.cid; // args if( selector ) { args = [ event, selector, callback ]; } else { args = [ event, callback ]; } // on() $el.on.apply($el, args); }, /** * off * * Removes an event handler similar to jQuery * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ off: function( a1, a2 ,a3 ){ // vars var $el, event, selector, args; // find args if( a1 instanceof jQuery ) { // 1. args( $el, event, selector ) if( a3 ) { $el = a1; event = a2; selector = a3; // 2. args( $el, event ) } else { $el = a1; event = a2; } } else { // 3. args( event, selector ) if( a2 ) { event = a1; selector = a2; // 4. args( event ) } else { event = a1; } } // element $el = this.getEventTarget( $el ); // modify event event = event + '.' + this.cid; // args if( selector ) { args = [ event, selector ]; } else { args = [ event ]; } // off() $el.off.apply($el, args); }, /** * trigger * * Triggers an event similar to jQuery * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ trigger: function( name, args, bubbles ){ var $el = this.getEventTarget(); if( bubbles ) { $el.trigger.apply( $el, arguments ); } else { $el.triggerHandler.apply( $el, arguments ); } return this; }, /** * addActions * * Adds multiple action handlers * * @date 14/12/17 * @since 5.6.5 * * @param object actions {action1 : callback, action2 : callback, etc } * @return n/a */ addActions: function( actions ){ actions = actions || this.actions || null; if( !actions ) return false; for( var i in actions ) { this.addAction( i, actions[i] ); } }, /** * removeActions * * Removes multiple action handlers * * @date 14/12/17 * @since 5.6.5 * * @param object actions {action1 : callback, action2 : callback, etc } * @return n/a */ removeActions: function( actions ){ actions = actions || this.actions || null; if( !actions ) return false; for( var i in actions ) { this.removeAction( i, actions[i] ); } }, /** * addAction * * Adds an action using the wp.hooks library * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ addAction: function( name, callback, priority ){ //console.log('addAction', name, priority); // defaults priority = priority || this.priority; // modify callback if( typeof callback === 'string' ) { callback = this[ callback ]; } // add acf.addAction(name, callback, priority, this); }, /** * removeAction * * Remove an action using the wp.hooks library * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ removeAction: function( name, callback ){ acf.removeAction(name, this[ callback ]); }, /** * addFilters * * Adds multiple filter handlers * * @date 14/12/17 * @since 5.6.5 * * @param object filters {filter1 : callback, filter2 : callback, etc } * @return n/a */ addFilters: function( filters ){ filters = filters || this.filters || null; if( !filters ) return false; for( var i in filters ) { this.addFilter( i, filters[i] ); } }, /** * addFilter * * Adds a filter using the wp.hooks library * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ addFilter: function( name, callback, priority ){ // defaults priority = priority || this.priority; // modify callback if( typeof callback === 'string' ) { callback = this[ callback ]; } // add acf.addFilter(name, callback, priority, this); }, /** * removeFilters * * Removes multiple filter handlers * * @date 14/12/17 * @since 5.6.5 * * @param object filters {filter1 : callback, filter2 : callback, etc } * @return n/a */ removeFilters: function( filters ){ filters = filters || this.filters || null; if( !filters ) return false; for( var i in filters ) { this.removeFilter( i, filters[i] ); } }, /** * removeFilter * * Remove a filter using the wp.hooks library * * @date 14/12/17 * @since 5.6.5 * * @param string name * @param string callback * @return n/a */ removeFilter: function( name, callback ){ acf.removeFilter(name, this[ callback ]); }, /** * $ * * description * * @date 16/12/17 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ $: function( selector ){ return this.$el.find( selector ); }, /** * remove * * Removes the element and listenters * * @date 19/12/17 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ remove: function(){ this.removeEvents(); this.removeActions(); this.removeFilters(); this.$el.remove(); }, /** * setTimeout * * description * * @date 16/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ setTimeout: function( callback, milliseconds ){ return setTimeout( this.proxy(callback), milliseconds ); }, /** * time * * used for debugging * * @date 7/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ time: function(){ console.time( this.id || this.cid ); }, /** * timeEnd * * used for debugging * * @date 7/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ timeEnd: function(){ console.timeEnd( this.id || this.cid ); }, /** * show * * description * * @date 15/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ show: function(){ acf.show( this.$el ); }, /** * hide * * description * * @date 15/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ hide: function(){ acf.hide( this.$el ); }, /** * proxy * * Returns a new function scoped to this model * * @date 29/3/18 * @since 5.6.9 * * @param function callback * @return function */ proxy: function( callback ){ return $.proxy( callback, this ); } }); // Set up inheritance for the model Model.extend = extend; // Global model storage acf.models = {}; /** * acf.getInstance * * This function will get an instance from an element * * @date 5/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ acf.getInstance = function( $el ){ return $el.data('acf'); }; /** * acf.getInstances * * This function will get an array of instances from multiple elements * * @date 5/3/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ acf.getInstances = function( $el ){ var instances = []; $el.each(function(){ instances.push( acf.getInstance( $(this) ) ); }); return instances; }; })(jQuery); (function($, undefined){ acf.models.Popup = acf.Model.extend({ data: { title: '', content: '', width: 0, height: 0, loading: false }, events: { 'click [data-event="close"]': 'onClickClose', 'click .acf-close-popup': 'onClickClose', }, setup: function( props ){ $.extend(this.data, props); this.$el = $(this.tmpl()); }, initialize: function(){ this.render(); this.open(); }, tmpl: function(){ return [ '<div id="acf-popup">', '<div class="acf-popup-box acf-box">', '<div class="title"><h3></h3><a href="#" class="acf-icon -cancel grey" data-event="close"></a></div>', '<div class="inner"></div>', '<div class="loading"><i class="acf-loading"></i></div>', '</div>', '<div class="bg" data-event="close"></div>', '</div>' ].join(''); }, render: function(){ // Extract Vars. var title = this.get('title'); var content = this.get('content'); var loading = this.get('loading'); var width = this.get('width'); var height = this.get('height'); // Update. this.title( title ); this.content( content ); if( width ) { this.$('.acf-popup-box').css('width', width); } if( height ) { this.$('.acf-popup-box').css('min-height', height); } this.loading( loading ); // Trigger action. acf.doAction('append', this.$el); }, update: function( props ){ this.data = acf.parseArgs(props, this.data); this.render(); }, title: function( title ){ this.$('.title:first h3').html( title ); }, content: function( content ){ this.$('.inner:first').html( content ); }, loading: function( show ){ var $loading = this.$('.loading:first'); show ? $loading.show() : $loading.hide(); }, open: function(){ $('body').append( this.$el ); }, close: function(){ this.remove(); }, onClickClose: function( e, $el ){ e.preventDefault(); this.close(); } }); /** * newPopup * * Creates a new Popup with the supplied props * * @date 17/12/17 * @since 5.6.5 * * @param object props * @return object */ acf.newPopup = function( props ){ return new acf.models.Popup( props ); }; })(jQuery); (function($, undefined){ acf.models.Modal = acf.Model.extend({ data: { title: '', content: '', toolbar: '', }, events: { 'click .acf-modal-close': 'onClickClose', }, setup: function( props ){ $.extend(this.data, props); this.$el = $(); this.render(); }, initialize: function(){ this.open(); }, render: function(){ // Extract vars. var title = this.get('title'); var content = this.get('content'); var toolbar = this.get('toolbar'); // Create element. var $el = $([ '<div>', '<div class="acf-modal">', '<div class="acf-modal-title">', '<h2>' + title + '</h2>', '<button class="acf-modal-close" type="button"><span class="dashicons dashicons-no"></span></button>', '</div>', '<div class="acf-modal-content">' + content + '</div>', '<div class="acf-modal-toolbar">' + toolbar + '</div>', '</div>', '<div class="acf-modal-backdrop acf-modal-close"></div>', '</div>' ].join('') ); // Update DOM. if( this.$el ) { this.$el.replaceWith( $el ); } this.$el = $el; // Trigger action. acf.doAction('append', $el); }, update: function( props ){ this.data = acf.parseArgs(props, this.data); this.render(); }, title: function( title ){ this.$('.acf-modal-title h2').html( title ); }, content: function( content ){ this.$('.acf-modal-content').html( content ); }, toolbar: function( toolbar ){ this.$('.acf-modal-toolbar').html( toolbar ); }, open: function(){ $('body').append( this.$el ); }, close: function(){ this.remove(); }, onClickClose: function( e, $el ){ e.preventDefault(); this.close(); } }); /** * Returns a new modal. * * @date 21/4/20 * @since 5.9.0 * * @param object props The modal props. * @return object */ acf.newModal = function( props ){ return new acf.models.Modal( props ); }; })(jQuery); (function($, undefined){ var panel = new acf.Model({ events: { 'click .acf-panel-title': 'onClick', }, onClick: function( e, $el ){ e.preventDefault(); this.toggle( $el.parent() ); }, isOpen: function( $el ) { return $el.hasClass('-open'); }, toggle: function( $el ){ this.isOpen($el) ? this.close( $el ) : this.open( $el ); }, open: function( $el ){ $el.addClass('-open'); $el.find('.acf-panel-title i').attr('class', 'dashicons dashicons-arrow-down'); }, close: function( $el ){ $el.removeClass('-open'); $el.find('.acf-panel-title i').attr('class', 'dashicons dashicons-arrow-right'); } }); })(jQuery); (function($, undefined){ var Notice = acf.Model.extend({ data: { text: '', type: '', timeout: 0, dismiss: true, target: false, close: function(){} }, events: { 'click .acf-notice-dismiss': 'onClickClose', }, tmpl: function(){ return '<div class="acf-notice"></div>'; }, setup: function( props ){ $.extend(this.data, props); this.$el = $(this.tmpl()); }, initialize: function(){ // render this.render(); // show this.show(); }, render: function(){ // class this.type( this.get('type') ); // text this.html( '<p>' + this.get('text') + '</p>' ); // close if( this.get('dismiss') ) { this.$el.append('<a href="#" class="acf-notice-dismiss acf-icon -cancel small"></a>'); this.$el.addClass('-dismiss'); } // timeout var timeout = this.get('timeout'); if( timeout ) { this.away( timeout ); } }, update: function( props ){ // update $.extend(this.data, props); // re-initialize this.initialize(); // refresh events this.removeEvents(); this.addEvents(); }, show: function(){ var $target = this.get('target'); if( $target ) { $target.prepend( this.$el ); } }, hide: function(){ this.$el.remove(); }, away: function( timeout ){ this.setTimeout(function(){ acf.remove( this.$el ); }, timeout ); }, type: function( type ){ // remove prev type var prevType = this.get('type'); if( prevType ) { this.$el.removeClass('-' + prevType); } // add new type this.$el.addClass('-' + type); // backwards compatibility if( type == 'error' ) { this.$el.addClass('acf-error-message'); } }, html: function( html ){ this.$el.html( acf.escHtml( html ) ); }, text: function( text ){ this.$('p').html( acf.escHtml( text ) ); }, onClickClose: function( e, $el ){ e.preventDefault(); this.get('close').apply(this, arguments); this.remove(); } }); acf.newNotice = function( props ){ // ensure object if( typeof props !== 'object' ) { props = { text: props }; } // instantiate return new Notice( props ); }; var noticeManager = new acf.Model({ wait: 'prepare', priority: 1, initialize: function(){ // vars var $notice = $('.acf-admin-notice'); // move to avoid WP flicker if( $notice.length ) { $('h1:first').after( $notice ); } } }); })(jQuery); (function($, undefined){ acf.newTooltip = function( props ){ // ensure object if( typeof props !== 'object' ) { props = { text: props }; } // confirmRemove if( props.confirmRemove !== undefined ) { props.textConfirm = acf.__('Remove'); props.textCancel = acf.__('Cancel'); return new TooltipConfirm( props ); // confirm } else if( props.confirm !== undefined ) { return new TooltipConfirm( props ); // default } else { return new Tooltip( props ); } }; var Tooltip = acf.Model.extend({ data: { text: '', timeout: 0, target: null }, tmpl: function(){ return '<div class="acf-tooltip"></div>'; }, setup: function( props ){ $.extend(this.data, props); this.$el = $(this.tmpl()); }, initialize: function(){ // render this.render(); // append this.show(); // position this.position(); // timeout var timeout = this.get('timeout'); if( timeout ) { setTimeout( $.proxy(this.fade, this), timeout ); } }, update: function( props ){ $.extend(this.data, props); this.initialize(); }, render: function(){ this.html( this.get('text') ); }, show: function(){ $('body').append( this.$el ); }, hide: function(){ this.$el.remove(); }, fade: function(){ // add class this.$el.addClass('acf-fade-up'); // remove this.setTimeout(function(){ this.remove(); }, 250); }, html: function( html ){ this.$el.html( html ); }, position: function(){ // vars var $tooltip = this.$el; var $target = this.get('target'); if( !$target ) return; // Reset position. $tooltip.removeClass('right left bottom top').css({ top: 0, left: 0 }); // Declare tollerance to edge of screen. var tolerance = 10; // Find target position. var targetWidth = $target.outerWidth(); var targetHeight = $target.outerHeight(); var targetTop = $target.offset().top; var targetLeft = $target.offset().left; // Find tooltip position. var tooltipWidth = $tooltip.outerWidth(); var tooltipHeight = $tooltip.outerHeight(); var tooltipTop = $tooltip.offset().top; // Should be 0, but WP media grid causes this to be 32 (toolbar padding). // Assume default top alignment. var top = targetTop - tooltipHeight - tooltipTop; var left = targetLeft + (targetWidth / 2) - (tooltipWidth / 2); // Check if too far left. if( left < tolerance ) { $tooltip.addClass('right'); left = targetLeft + targetWidth; top = targetTop + (targetHeight / 2) - (tooltipHeight / 2) - tooltipTop; // Check if too far right. } else if( (left + tooltipWidth + tolerance) > $(window).width() ) { $tooltip.addClass('left'); left = targetLeft - tooltipWidth; top = targetTop + (targetHeight / 2) - (tooltipHeight / 2) - tooltipTop; // Check if too far up. } else if( top - $(window).scrollTop() < tolerance ) { $tooltip.addClass('bottom'); top = targetTop + targetHeight - tooltipTop; // No colision with edges. } else { $tooltip.addClass('top'); } // update css $tooltip.css({ 'top': top, 'left': left }); } }); var TooltipConfirm = Tooltip.extend({ data: { text: '', textConfirm: '', textCancel: '', target: null, targetConfirm: true, confirm: function(){}, cancel: function(){}, context: false }, events: { 'click [data-event="cancel"]': 'onCancel', 'click [data-event="confirm"]': 'onConfirm', }, addEvents: function(){ // add events acf.Model.prototype.addEvents.apply(this); // vars var $document = $(document); var $target = this.get('target'); // add global 'cancel' click event // - use timeout to avoid the current 'click' event triggering the onCancel function this.setTimeout(function(){ this.on( $document, 'click', 'onCancel' ); }); // add target 'confirm' click event // - allow setting to control this feature if( this.get('targetConfirm') ) { this.on( $target, 'click', 'onConfirm' ); } }, removeEvents: function(){ // remove events acf.Model.prototype.removeEvents.apply(this); // vars var $document = $(document); var $target = this.get('target'); // remove custom events this.off( $document, 'click' ); this.off( $target, 'click' ); }, render: function(){ // defaults var text = this.get('text') || acf.__('Are you sure?'); var textConfirm = this.get('textConfirm') || acf.__('Yes'); var textCancel = this.get('textCancel') || acf.__('No'); // html var html = [ text, '<a href="#" data-event="confirm">' + textConfirm + '</a>', '<a href="#" data-event="cancel">' + textCancel + '</a>' ].join(' '); // html this.html( html ); // class this.$el.addClass('-confirm'); }, onCancel: function( e, $el ){ // prevent default e.preventDefault(); e.stopImmediatePropagation(); // callback var callback = this.get('cancel'); var context = this.get('context') || this; callback.apply( context, arguments ); //remove this.remove(); }, onConfirm: function( e, $el ){ // Prevent event from propagating completely to allow "targetConfirm" to be clicked. e.preventDefault(); e.stopImmediatePropagation(); // callback var callback = this.get('confirm'); var context = this.get('context') || this; callback.apply( context, arguments ); //remove this.remove(); } }); // storage acf.models.Tooltip = Tooltip; acf.models.TooltipConfirm = TooltipConfirm; /** * tooltipManager * * description * * @date 17/4/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ var tooltipHoverHelper = new acf.Model({ tooltip: false, events: { 'mouseenter .acf-js-tooltip': 'showTitle', 'mouseup .acf-js-tooltip': 'hideTitle', 'mouseleave .acf-js-tooltip': 'hideTitle' }, showTitle: function( e, $el ){ // vars var title = $el.attr('title'); // bail ealry if no title if( !title ) { return; } // clear title to avoid default browser tooltip $el.attr('title', ''); // create if( !this.tooltip ) { this.tooltip = acf.newTooltip({ text: title, target: $el }); // update } else { this.tooltip.update({ text: title, target: $el }); } }, hideTitle: function( e, $el ){ // hide tooltip this.tooltip.hide(); // restore title $el.attr('title', this.tooltip.get('text')); } }); })(jQuery); // @codekit-prepend "_acf.js"; // @codekit-prepend "_acf-hooks.js"; // @codekit-prepend "_acf-model.js"; // @codekit-prepend "_acf-popup.js"; // @codekit-prepend "_acf-modal.js"; // @codekit-prepend "_acf-panel.js"; // @codekit-prepend "_acf-notice.js"; // @codekit-prepend "_acf-tooltip.js";