(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 ){ // replace [_-] characters with space str = str.replace(/[_-]/g, ' '); // camelCase str = str.replace(/(?:^\w|\b\w|\s+)/g, function(match, index) { if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces return index == 0 ? match.toLowerCase() : match.toUpperCase(); }); // return return str; }; /** * 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; }; /** * acf.decode * * description * * @date 13/1/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.decode = function( string ){ return $('').html( string ).text(); }; /** * acf.strEscape * * description * * @date 3/2/18 * @since 5.6.5 * * @param type $var Description. Default. * @return type Description. */ acf.strEscape = function( string ){ var entityMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' }; return String(string).replace(/[&<>"'`=\/]/g, function (s) { return entityMap[s]; }); }; /** * 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('
'); 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 = $('