diff --git a/acf.php b/acf.php
index f1b0884..2a71eb4 100644
--- a/acf.php
+++ b/acf.php
@@ -3,7 +3,7 @@
Plugin Name: Advanced Custom Fields PRO
Plugin URI: https://www.advancedcustomfields.com
Description: Customize WordPress with powerful, professional and intuitive fields.
-Version: 5.9.8
+Version: 5.9.9
Author: Delicious Brains
Author URI: https://www.advancedcustomfields.com
Text Domain: acf
@@ -17,7 +17,7 @@ if( ! class_exists('ACF') ) :
class ACF {
/** @var string The plugin version number. */
- var $version = '5.9.8';
+ var $version = '5.9.9';
/** @var array The plugin settings array. */
var $settings = array();
diff --git a/assets/build/js/acf-field-group.js b/assets/build/js/acf-field-group.js
index a29bfdc..50c0de6 100644
--- a/assets/build/js/acf-field-group.js
+++ b/assets/build/js/acf-field-group.js
@@ -1,2050 +1,2525 @@
-(function ($, undefined) {
- /**
- * fieldGroupManager
- *
- * Generic field group functionality
- *
- * @date 15/12/17
- * @since 5.7.0
- *
- * @param void
- * @return void
- */
- var fieldGroupManager = new acf.Model({
- id: 'fieldGroupManager',
- events: {
- 'submit #post': 'onSubmit',
- 'click a[href="#"]': 'onClick',
- 'click .submitdelete': 'onClickTrash'
- },
- filters: {
- 'find_fields_args': 'filterFindFieldArgs'
- },
- onSubmit: function (e, $el) {
- // vars
- var $title = $('#titlewrap #title'); // empty
-
- if (!$title.val()) {
- // prevent default
- e.preventDefault(); // unlock form
-
- acf.unlockForm($el); // alert
-
- alert(acf.__('Field group title is required')); // focus
-
- $title.trigger('focus');
- }
- },
- onClick: function (e) {
- e.preventDefault();
- },
- onClickTrash: function (e) {
- var result = confirm(acf.__('Move to trash. Are you sure?'));
-
- if (!result) {
- e.preventDefault();
- }
- },
- filterFindFieldArgs: function (args) {
- args.visible = true;
- return args;
- }
- });
- /**
- * screenOptionsManager
- *
- * Screen options functionality
- *
- * @date 15/12/17
- * @since 5.7.0
- *
- * @param void
- * @return void
- */
-
- var screenOptionsManager = new acf.Model({
- id: 'screenOptionsManager',
- wait: 'prepare',
- events: {
- 'change': 'onChange'
- },
- initialize: function () {
- // vars
- var $div = $('#adv-settings');
- var $append = $('#acf-append-show-on-screen'); // append
-
- $div.find('.metabox-prefs').append($append.html());
- $div.find('.metabox-prefs br').remove(); // clean up
-
- $append.remove(); // initialize
-
- this.$el = $('#acf-field-key-hide'); // render
-
- this.render();
- },
- isChecked: function () {
- return this.$el.prop('checked');
- },
- onChange: function (e, $el) {
- var val = this.isChecked() ? 1 : 0;
- acf.updateUserSetting('show_field_keys', val);
- this.render();
- },
- render: function () {
- if (this.isChecked()) {
- $('#acf-field-group-fields').addClass('show-field-keys');
- } else {
- $('#acf-field-group-fields').removeClass('show-field-keys');
- }
- }
- });
- /**
- * appendFieldManager
- *
- * Appends fields together
- *
- * @date 15/12/17
- * @since 5.7.0
- *
- * @param void
- * @return void
- */
-
- var appendFieldManager = new acf.Model({
- actions: {
- 'new_field': 'onNewField'
- },
- onNewField: function (field) {
- // bail ealry if not append
- if (!field.has('append')) return; // vars
-
- var append = field.get('append');
- var $sibling = field.$el.siblings('[data-name="' + append + '"]').first(); // bail early if no sibling
-
- if (!$sibling.length) return; // ul
-
- var $div = $sibling.children('.acf-input');
- var $ul = $div.children('ul'); // create ul
-
- if (!$ul.length) {
- $div.wrapInner('
');
- $ul = $div.children('ul');
- } // li
-
-
- var html = field.$('.acf-input').html();
- var $li = $('' + html + ' ');
- $ul.append($li);
- $ul.attr('data-cols', $ul.children().length); // clean up
-
- field.remove();
- }
- });
+(function($, undefined){
+
+ /**
+ * fieldGroupManager
+ *
+ * Generic field group functionality
+ *
+ * @date 15/12/17
+ * @since 5.7.0
+ *
+ * @param void
+ * @return void
+ */
+
+ var fieldGroupManager = new acf.Model({
+
+ id: 'fieldGroupManager',
+
+ events: {
+ 'submit #post': 'onSubmit',
+ 'click a[href="#"]': 'onClick',
+ 'click .submitdelete': 'onClickTrash',
+ },
+
+ filters: {
+ 'find_fields_args': 'filterFindFieldArgs'
+ },
+
+ onSubmit: function( e, $el ){
+
+ // vars
+ var $title = $('#titlewrap #title');
+
+ // empty
+ if( !$title.val() ) {
+
+ // prevent default
+ e.preventDefault();
+
+ // unlock form
+ acf.unlockForm( $el );
+
+ // alert
+ alert( acf.__('Field group title is required') );
+
+ // focus
+ $title.trigger('focus');
+ }
+ },
+
+ onClick: function( e ){
+ e.preventDefault();
+ },
+
+ onClickTrash: function( e ){
+ var result = confirm( acf.__('Move to trash. Are you sure?') );
+ if( !result ) {
+ e.preventDefault();
+ }
+ },
+
+ filterFindFieldArgs: function( args ){
+ args.visible = true;
+ return args;
+ }
+ });
+
+
+ /**
+ * screenOptionsManager
+ *
+ * Screen options functionality
+ *
+ * @date 15/12/17
+ * @since 5.7.0
+ *
+ * @param void
+ * @return void
+ */
+
+ var screenOptionsManager = new acf.Model({
+
+ id: 'screenOptionsManager',
+ wait: 'prepare',
+
+ events: {
+ 'change': 'onChange'
+ },
+
+ initialize: function(){
+
+ // vars
+ var $div = $('#adv-settings');
+ var $append = $('#acf-append-show-on-screen');
+
+ // append
+ $div.find('.metabox-prefs').append( $append.html() );
+ $div.find('.metabox-prefs br').remove();
+
+ // clean up
+ $append.remove();
+
+ // initialize
+ this.$el = $('#acf-field-key-hide');
+
+ // render
+ this.render();
+ },
+
+ isChecked: function(){
+ return this.$el.prop('checked');
+ },
+
+ onChange: function( e, $el ) {
+ var val = this.isChecked() ? 1 : 0;
+ acf.updateUserSetting('show_field_keys', val);
+ this.render();
+ },
+
+ render: function(){
+ if( this.isChecked() ) {
+ $('#acf-field-group-fields').addClass('show-field-keys');
+ } else {
+ $('#acf-field-group-fields').removeClass('show-field-keys');
+ }
+ }
+
+ });
+
+
+ /**
+ * appendFieldManager
+ *
+ * Appends fields together
+ *
+ * @date 15/12/17
+ * @since 5.7.0
+ *
+ * @param void
+ * @return void
+ */
+
+ var appendFieldManager = new acf.Model({
+
+ actions: {
+ 'new_field' : 'onNewField'
+ },
+
+ onNewField: function( field ){
+
+ // bail ealry if not append
+ if( !field.has('append') ) return;
+
+ // vars
+ var append = field.get('append');
+ var $sibling = field.$el.siblings('[data-name="' + append + '"]').first();
+
+ // bail early if no sibling
+ if( !$sibling.length ) return;
+
+ // ul
+ var $div = $sibling.children('.acf-input');
+ var $ul = $div.children('ul');
+
+ // create ul
+ if( !$ul.length ) {
+ $div.wrapInner('');
+ $ul = $div.children('ul');
+ }
+
+ // li
+ var html = field.$('.acf-input').html();
+ var $li = $('' + html + ' ');
+ $ul.append( $li );
+ $ul.attr('data-cols', $ul.children().length );
+
+ // clean up
+ field.remove();
+ }
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- acf.FieldObject = acf.Model.extend({
- // class used to avoid nested event triggers
- eventScope: '.acf-field-object',
- // events
- events: {
- 'click .edit-field': 'onClickEdit',
- 'click .delete-field': 'onClickDelete',
- 'click .duplicate-field': 'duplicate',
- 'click .move-field': 'move',
- 'change .field-type': 'onChangeType',
- 'change .field-required': 'onChangeRequired',
- 'blur .field-label': 'onChangeLabel',
- 'blur .field-name': 'onChangeName',
- 'change': 'onChange',
- 'changed': 'onChanged'
- },
- // data
- data: {
- // Similar to ID, but used for HTML puposes.
- // It is possbile for a new field to have an ID of 0, but an id of 'field_123' */
- id: 0,
- // The field key ('field_123')
- key: '',
- // The field type (text, image, etc)
- type: '' // The $post->ID of this field
- //ID: 0,
- // The field's parent
- //parent: 0,
- // The menu order
- //menu_order: 0
-
- },
- setup: function ($field) {
- // set $el
- this.$el = $field; // inherit $field data (id, key, type)
-
- this.inherit($field); // load additional props
- // - this won't trigger 'changed'
-
- this.prop('ID');
- this.prop('parent');
- this.prop('menu_order');
- },
- $input: function (name) {
- return $('#' + this.getInputId() + '-' + name);
- },
- $meta: function () {
- return this.$('.meta:first');
- },
- $handle: function () {
- return this.$('.handle:first');
- },
- $settings: function () {
- return this.$('.settings:first');
- },
- $setting: function (name) {
- return this.$('.acf-field-settings:first > .acf-field-setting-' + name);
- },
- getParent: function () {
- return acf.getFieldObjects({
- child: this.$el,
- limit: 1
- }).pop();
- },
- getParents: function () {
- return acf.getFieldObjects({
- child: this.$el
- });
- },
- getFields: function () {
- return acf.getFieldObjects({
- parent: this.$el
- });
- },
- getInputName: function () {
- return 'acf_fields[' + this.get('id') + ']';
- },
- getInputId: function () {
- return 'acf_fields-' + this.get('id');
- },
- newInput: function (name, value) {
- // vars
- var inputId = this.getInputId();
- var inputName = this.getInputName(); // append name
-
- if (name) {
- inputId += '-' + name;
- inputName += '[' + name + ']';
- } // create input (avoid HTML + JSON value issues)
-
-
- var $input = $(' ').attr({
- id: inputId,
- name: inputName,
- value: value
- });
- this.$('> .meta').append($input); // return
-
- return $input;
- },
- getProp: function (name) {
- // check data
- if (this.has(name)) {
- return this.get(name);
- } // get input value
-
-
- var $input = this.$input(name);
- var value = $input.length ? $input.val() : null; // set data silently (cache)
-
- this.set(name, value, true); // return
-
- return value;
- },
- setProp: function (name, value) {
- // get input
- var $input = this.$input(name);
- var prevVal = $input.val(); // create if new
-
- if (!$input.length) {
- $input = this.newInput(name, value);
- } // remove
-
-
- if (value === null) {
- $input.remove(); // update
- } else {
- $input.val(value);
- } //console.log('setProp', name, value, this);
- // set data silently (cache)
-
-
- if (!this.has(name)) {
- //console.log('setting silently');
- this.set(name, value, true); // set data allowing 'change' event to fire
- } else {
- //console.log('setting loudly!');
- this.set(name, value);
- } // return
-
-
- return this;
- },
- prop: function (name, value) {
- if (value !== undefined) {
- return this.setProp(name, value);
- } else {
- return this.getProp(name);
- }
- },
- props: function (props) {
- Object.keys(props).map(function (key) {
- this.setProp(key, props[key]);
- }, this);
- },
- getLabel: function () {
- // get label with empty default
- var label = this.prop('label');
-
- if (label === '') {
- label = acf.__('(no label)');
- } // return
-
-
- return label;
- },
- getName: function () {
- return this.prop('name');
- },
- getType: function () {
- return this.prop('type');
- },
- getTypeLabel: function () {
- var type = this.prop('type');
- var types = acf.get('fieldTypes');
- return types[type] ? types[type].label : type;
- },
- getKey: function () {
- return this.prop('key');
- },
- initialize: function () {
- this.addProFields();
- },
- addProFields: function () {
- // Make sure we're only running this on free version.
- if (acf.data.fieldTypes.hasOwnProperty('clone')) {
- return;
- } // Make sure we haven't appended these fields before.
-
-
- var $fieldTypeSelect = $('.field-type').not('.acf-free-field-type'); // Append pro fields to "Layout" group.
-
- var $layoutGroup = $fieldTypeSelect.find('optgroup option[value="group"]').parent();
- $layoutGroup.append('' + acf.__('Repeater (Pro only)') + ' ' + '' + acf.__('Flexible Content (Pro only)') + ' ' + '' + acf.__('Clone (Pro only)') + ' '); // Add pro fields to "Content" group.
-
- var $contentGroup = $fieldTypeSelect.find('optgroup option[value="image"]').parent();
- $contentGroup.append('' + acf.__('Gallery (Pro only)') + ' ');
- $fieldTypeSelect.addClass('acf-free-field-type');
- },
- render: function () {
- // vars
- var $handle = this.$('.handle:first');
- var menu_order = this.prop('menu_order');
- var label = this.getLabel();
- var name = this.prop('name');
- var type = this.getTypeLabel();
- var key = this.prop('key');
- var required = this.$input('required').prop('checked'); // update menu order
-
- $handle.find('.acf-icon').html(parseInt(menu_order) + 1); // update required
-
- if (required) {
- label += ' * ';
- } // update label
-
-
- $handle.find('.li-field-label strong a').html(label); // update name
-
- $handle.find('.li-field-name').text(name); // update type
-
- $handle.find('.li-field-type').text(type); // update key
-
- $handle.find('.li-field-key').text(key); // action for 3rd party customization
-
- acf.doAction('render_field_object', this);
- },
- refresh: function () {
- acf.doAction('refresh_field_object', this);
- },
- isOpen: function () {
- return this.$el.hasClass('open');
- },
- onClickEdit: function (e) {
- this.isOpen() ? this.close() : this.open();
- },
- open: function () {
- // vars
- var $settings = this.$el.children('.settings'); // open
-
- $settings.slideDown();
- this.$el.addClass('open'); // action (open)
-
- acf.doAction('open_field_object', this);
- this.trigger('openFieldObject'); // action (show)
-
- acf.doAction('show', $settings);
- },
- close: function () {
- // vars
- var $settings = this.$el.children('.settings'); // close
-
- $settings.slideUp();
- this.$el.removeClass('open'); // action (close)
-
- acf.doAction('close_field_object', this);
- this.trigger('closeFieldObject'); // action (hide)
-
- acf.doAction('hide', $settings);
- },
- serialize: function () {
- return acf.serialize(this.$el, this.getInputName());
- },
- save: function (type) {
- // defaults
- type = type || 'settings'; // meta, settings
- // vars
-
- var save = this.getProp('save'); // bail if already saving settings
-
- if (save === 'settings') {
- return;
- } // prop
-
-
- this.setProp('save', type); // debug
-
- this.$el.attr('data-save', type); // action
-
- acf.doAction('save_field_object', this, type);
- },
- submit: function () {
- // vars
- var inputName = this.getInputName();
- var save = this.get('save'); // close
-
- if (this.isOpen()) {
- this.close();
- } // allow all inputs to save
-
-
- if (save == 'settings') {// do nothing
- // allow only meta inputs to save
- } else if (save == 'meta') {
- this.$('> .settings [name^="' + inputName + '"]').remove(); // prevent all inputs from saving
- } else {
- this.$('[name^="' + inputName + '"]').remove();
- } // action
-
-
- acf.doAction('submit_field_object', this);
- },
- onChange: function (e, $el) {
- // save settings
- this.save(); // action for 3rd party customization
-
- acf.doAction('change_field_object', this);
- },
- onChanged: function (e, $el, name, value) {
- // ignore 'save'
- if (name == 'save') {
- return;
- } // save meta
-
-
- if (['menu_order', 'parent'].indexOf(name) > -1) {
- this.save('meta'); // save field
- } else {
- this.save();
- } // render
-
-
- if (['menu_order', 'label', 'required', 'name', 'type', 'key'].indexOf(name) > -1) {
- this.render();
- } // action for 3rd party customization
-
-
- acf.doAction('change_field_object_' + name, this, value);
- },
- onChangeLabel: function (e, $el) {
- // set
- var label = $el.val();
- this.set('label', label); // render name
-
- if (this.prop('name') == '') {
- var name = acf.applyFilters('generate_field_object_name', acf.strSanitize(label), this);
- this.prop('name', name);
- }
- },
- onChangeName: function (e, $el) {
- // set
- var name = $el.val();
- this.set('name', name); // error
-
- if (name.substr(0, 6) === 'field_') {
- alert(acf.__('The string "field_" may not be used at the start of a field name'));
- }
- },
- onChangeRequired: function (e, $el) {
- // set
- var required = $el.prop('checked') ? 1 : 0;
- this.set('required', required);
- },
- delete: function (args) {
- // defaults
- args = acf.parseArgs(args, {
- animate: true
- }); // add to remove list
-
- var id = this.prop('ID');
-
- if (id) {
- var $input = $('#_acf_delete_fields');
- var newVal = $input.val() + '|' + id;
- $input.val(newVal);
- } // action
-
-
- acf.doAction('delete_field_object', this); // animate
-
- if (args.animate) {
- this.removeAnimate();
- } else {
- this.remove();
- }
- },
- onClickDelete: function (e, $el) {
- // Bypass confirmation when holding down "shift" key.
- if (e.shiftKey) {
- return this.delete();
- } // add class
-
-
- this.$el.addClass('-hover'); // add tooltip
-
- var tooltip = acf.newTooltip({
- confirmRemove: true,
- target: $el,
- context: this,
- confirm: function () {
- this.delete();
- },
- cancel: function () {
- this.$el.removeClass('-hover');
- }
- });
- },
- removeAnimate: function () {
- // vars
- var field = this;
- var $list = this.$el.parent();
- var $fields = acf.findFieldObjects({
- sibling: this.$el
- }); // remove
-
- acf.remove({
- target: this.$el,
- endHeight: $fields.length ? 0 : 50,
- complete: function () {
- field.remove();
- acf.doAction('removed_field_object', field, $list);
- }
- }); // action
-
- acf.doAction('remove_field_object', field, $list);
- },
- duplicate: function () {
- // vars
- var newKey = acf.uniqid('field_'); // duplicate
-
- var $newField = acf.duplicate({
- target: this.$el,
- search: this.get('id'),
- replace: newKey
- }); // set new key
-
- $newField.attr('data-key', newKey); // get instance
-
- var newField = acf.getFieldObject($newField); // open / close
-
- if (this.isOpen()) {
- this.close();
- } else {
- newField.open();
- } // focus label
-
-
- var $label = newField.$setting('label input');
- setTimeout(function () {
- $label.trigger('focus');
- }, 251); // update newField label / name
-
- var label = newField.prop('label');
- var name = newField.prop('name');
- var end = name.split('_').pop();
-
- var copy = acf.__('copy'); // increase suffix "1"
-
-
- if (acf.isNumeric(end)) {
- var i = end * 1 + 1;
- label = label.replace(end, i);
- name = name.replace(end, i); // increase suffix "(copy1)"
- } else if (end.indexOf(copy) === 0) {
- var i = end.replace(copy, '') * 1;
- i = i ? i + 1 : 2; // replace
-
- label = label.replace(end, copy + i);
- name = name.replace(end, copy + i); // add default "(copy)"
- } else {
- label += ' (' + copy + ')';
- name += '_' + copy;
- }
-
- newField.prop('ID', 0);
- newField.prop('label', label);
- newField.prop('name', name);
- newField.prop('key', newKey); // action
-
- acf.doAction('duplicate_field_object', this, newField);
- acf.doAction('append_field_object', newField);
- },
- wipe: function () {
- // vars
- var prevId = this.get('id');
- var prevKey = this.get('key');
- var newKey = acf.uniqid('field_'); // rename
-
- acf.rename({
- target: this.$el,
- search: prevId,
- replace: newKey
- }); // data
-
- this.set('id', newKey);
- this.set('prevId', prevId);
- this.set('prevKey', prevKey); // props
-
- this.prop('key', newKey);
- this.prop('ID', 0); // attr
-
- this.$el.attr('data-key', newKey);
- this.$el.attr('data-id', newKey); // action
-
- acf.doAction('wipe_field_object', this);
- },
- move: function () {
- // helper
- var hasChanged = function (field) {
- return field.get('save') == 'settings';
- }; // vars
-
-
- var changed = hasChanged(this); // has sub fields changed
-
- if (!changed) {
- acf.getFieldObjects({
- parent: this.$el
- }).map(function (field) {
- changed = hasChanged(field) || field.changed;
- });
- } // bail early if changed
-
-
- if (changed) {
- alert(acf.__('This field cannot be moved until its changes have been saved'));
- return;
- } // step 1.
-
-
- var id = this.prop('ID');
- var field = this;
- var popup = false;
-
- var step1 = function () {
- // popup
- popup = acf.newPopup({
- title: acf.__('Move Custom Field'),
- loading: true,
- width: '300px'
- }); // ajax
-
- var ajaxData = {
- action: 'acf/field_group/move_field',
- field_id: id
- }; // get HTML
-
- $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'html',
- success: step2
- });
- };
-
- var step2 = function (html) {
- // update popup
- popup.loading(false);
- popup.content(html); // submit form
-
- popup.on('submit', 'form', step3);
- };
-
- var step3 = function (e, $el) {
- // prevent
- e.preventDefault(); // disable
-
- acf.startButtonLoading(popup.$('.button')); // ajax
-
- var ajaxData = {
- action: 'acf/field_group/move_field',
- field_id: id,
- field_group_id: popup.$('select').val()
- }; // get HTML
-
- $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'html',
- success: step4
- });
- };
-
- var step4 = function (html) {
- // update popup
- popup.content(html); // remove element
-
- field.removeAnimate();
- }; // start
-
-
- step1();
- },
- onChangeType: function (e, $el) {
- // clea previous timout
- if (this.changeTimeout) {
- clearTimeout(this.changeTimeout);
- } // set new timeout
- // - prevents changing type multiple times whilst user types in newType
-
-
- this.changeTimeout = this.setTimeout(function () {
- this.changeType($el.val());
- }, 300);
- },
- changeType: function (newType) {
- // vars
- var prevType = this.prop('type');
- var prevClass = acf.strSlugify('acf-field-object-' + prevType);
- var newClass = acf.strSlugify('acf-field-object-' + newType); // update props
-
- this.$el.removeClass(prevClass).addClass(newClass);
- this.$el.attr('data-type', newType);
- this.$el.data('type', newType); // abort XHR if this field is already loading AJAX data
-
- if (this.has('xhr')) {
- this.get('xhr').abort();
- } // store settings
-
-
- var $tbody = this.$('> .settings > table > tbody');
- var $settings = $tbody.children('[data-setting="' + prevType + '"]');
- this.set('settings-' + prevType, $settings);
- $settings.detach(); // show settings
-
- if (this.has('settings-' + newType)) {
- var $newSettings = this.get('settings-' + newType);
- this.$setting('conditional_logic').before($newSettings);
- this.set('type', newType); //this.refresh();
-
- return;
- } // load settings
-
-
- var $loading = $('
');
- this.$setting('conditional_logic').before($loading); // ajax
-
- var ajaxData = {
- action: 'acf/field_group/render_field_settings',
- field: this.serialize(),
- prefix: this.getInputName()
- }; // ajax
-
- var xhr = $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'html',
- context: this,
- success: function (html) {
- // bail early if no settings
- if (!html) return; // append settings
-
- $loading.after(html); // events
-
- acf.doAction('append', $tbody);
- },
- complete: function () {
- // also triggered by xhr.abort();
- $loading.remove();
- this.set('type', newType); //this.refresh();
- }
- }); // set
-
- this.set('xhr', xhr);
- },
- updateParent: function () {
- // vars
- var ID = acf.get('post_id'); // check parent
-
- var parent = this.getParent();
-
- if (parent) {
- ID = parseInt(parent.prop('ID')) || parent.prop('key');
- } // update
-
-
- this.prop('parent', ID);
- }
- });
+(function($, undefined){
+
+ acf.FieldObject = acf.Model.extend({
+
+ // class used to avoid nested event triggers
+ eventScope: '.acf-field-object',
+
+ // events
+ events: {
+ 'click .edit-field': 'onClickEdit',
+ 'click .delete-field': 'onClickDelete',
+ 'click .duplicate-field': 'duplicate',
+ 'click .move-field': 'move',
+
+ 'change .field-type': 'onChangeType',
+ 'change .field-required': 'onChangeRequired',
+ 'blur .field-label': 'onChangeLabel',
+ 'blur .field-name': 'onChangeName',
+
+ 'change': 'onChange',
+ 'changed': 'onChanged',
+ },
+
+ // data
+ data: {
+
+ // Similar to ID, but used for HTML puposes.
+ // It is possbile for a new field to have an ID of 0, but an id of 'field_123' */
+ id: 0,
+
+ // The field key ('field_123')
+ key: '',
+
+ // The field type (text, image, etc)
+ type: '',
+
+ // The $post->ID of this field
+ //ID: 0,
+
+ // The field's parent
+ //parent: 0,
+
+ // The menu order
+ //menu_order: 0
+ },
+
+ setup: function( $field ){
+
+ // set $el
+ this.$el = $field;
+
+ // inherit $field data (id, key, type)
+ this.inherit( $field );
+
+ // load additional props
+ // - this won't trigger 'changed'
+ this.prop('ID');
+ this.prop('parent');
+ this.prop('menu_order');
+ },
+
+ $input: function( name ){
+ return $('#' + this.getInputId() + '-' + name);
+ },
+
+ $meta: function(){
+ return this.$('.meta:first');
+ },
+
+ $handle: function(){
+ return this.$('.handle:first');
+ },
+
+ $settings: function(){
+ return this.$('.settings:first');
+ },
+
+ $setting: function( name ){
+ return this.$('.acf-field-settings:first > .acf-field-setting-' + name);
+ },
+
+ getParent: function(){
+ return acf.getFieldObjects({ child: this.$el, limit: 1 }).pop();
+ },
+
+ getParents: function(){
+ return acf.getFieldObjects({ child: this.$el });
+ },
+
+ getFields: function(){
+ return acf.getFieldObjects({ parent: this.$el });
+ },
+
+ getInputName: function(){
+ return 'acf_fields[' + this.get('id') + ']';
+ },
+
+ getInputId: function(){
+ return 'acf_fields-' + this.get('id');
+ },
+
+ newInput: function( name, value ){
+
+ // vars
+ var inputId = this.getInputId();
+ var inputName = this.getInputName();
+
+ // append name
+ if( name ) {
+ inputId += '-'+name;
+ inputName += '['+name+']';
+ }
+
+ // create input (avoid HTML + JSON value issues)
+ var $input = $(' ').attr({
+ id: inputId,
+ name: inputName,
+ value: value
+ });
+ this.$('> .meta').append( $input );
+
+ // return
+ return $input;
+ },
+
+ getProp: function( name ){
+
+ // check data
+ if( this.has(name) ) {
+ return this.get(name);
+ }
+
+ // get input value
+ var $input = this.$input( name );
+ var value = $input.length ? $input.val() : null;
+
+ // set data silently (cache)
+ this.set(name, value, true);
+
+ // return
+ return value;
+ },
+
+ setProp: function( name, value ) {
+
+ // get input
+ var $input = this.$input( name );
+ var prevVal = $input.val();
+
+ // create if new
+ if( !$input.length ) {
+ $input = this.newInput( name, value );
+ }
+
+ // remove
+ if( value === null ) {
+ $input.remove();
+
+ // update
+ } else {
+ $input.val( value );
+ }
+
+ //console.log('setProp', name, value, this);
+
+ // set data silently (cache)
+ if( !this.has(name) ) {
+ //console.log('setting silently');
+ this.set(name, value, true);
+
+ // set data allowing 'change' event to fire
+ } else {
+ //console.log('setting loudly!');
+ this.set(name, value);
+ }
+
+ // return
+ return this;
+
+ },
+
+ prop: function( name, value ){
+ if( value !== undefined ) {
+ return this.setProp( name, value );
+ } else {
+ return this.getProp( name );
+ }
+ },
+
+ props: function( props ){
+ Object.keys( props ).map(function( key ){
+ this.setProp( key, props[key] );
+ }, this);
+ },
+
+ getLabel: function(){
+
+ // get label with empty default
+ var label = this.prop('label');
+ if( label === '' ) {
+ label = acf.__('(no label)')
+ }
+
+ // return
+ return label;
+ },
+
+ getName: function(){
+ return this.prop('name');
+ },
+
+ getType: function(){
+ return this.prop('type');
+ },
+
+ getTypeLabel: function(){
+ var type = this.prop('type');
+ var types = acf.get('fieldTypes');
+ return ( types[type] ) ? types[type].label : type;
+ },
+
+ getKey: function(){
+ return this.prop('key');
+ },
+
+ initialize: function(){
+ this.addProFields();
+ },
+
+ addProFields: function() {
+ // Make sure we're only running this on free version.
+ if (acf.data.fieldTypes.hasOwnProperty('clone')) {
+ return;
+ }
+
+ // Make sure we haven't appended these fields before.
+ var $fieldTypeSelect = $('.field-type').not('.acf-free-field-type');
+
+ // Append pro fields to "Layout" group.
+ var $layoutGroup = $fieldTypeSelect.find('optgroup option[value="group"]').parent();
+ $layoutGroup.append(
+ '' + acf.__('Repeater (Pro only)') + ' ' +
+ '' + acf.__('Flexible Content (Pro only)') + ' ' +
+ '' + acf.__('Clone (Pro only)') + ' '
+ );
+
+ // Add pro fields to "Content" group.
+ var $contentGroup = $fieldTypeSelect.find('optgroup option[value="image"]').parent();
+ $contentGroup.append(
+ '' + acf.__('Gallery (Pro only)') + ' '
+ );
+
+ $fieldTypeSelect.addClass('acf-free-field-type');
+ },
+
+ render: function(){
+
+ // vars
+ var $handle = this.$('.handle:first');
+ var menu_order = this.prop('menu_order');
+ var label = this.getLabel();
+ var name = this.prop('name');
+ var type = this.getTypeLabel();
+ var key = this.prop('key');
+ var required = this.$input('required').prop('checked');
+
+ // update menu order
+ $handle.find('.acf-icon').html( parseInt(menu_order) + 1 );
+
+ // update required
+ if( required ) {
+ label += ' * ';
+ }
+
+ // update label
+ $handle.find('.li-field-label strong a').html( label );
+
+ // update name
+ $handle.find('.li-field-name').text( name );
+
+ // update type
+ $handle.find('.li-field-type').text( type );
+
+ // update key
+ $handle.find('.li-field-key').text( key );
+
+ // action for 3rd party customization
+ acf.doAction('render_field_object', this);
+ },
+
+ refresh: function(){
+ acf.doAction('refresh_field_object', this);
+ },
+
+ isOpen: function() {
+ return this.$el.hasClass('open');
+ },
+
+ onClickEdit: function( e ){
+ this.isOpen() ? this.close() : this.open();
+ },
+
+ open: function(){
+
+ // vars
+ var $settings = this.$el.children('.settings');
+
+ // open
+ $settings.slideDown();
+ this.$el.addClass('open');
+
+ // action (open)
+ acf.doAction('open_field_object', this);
+ this.trigger('openFieldObject');
+
+ // action (show)
+ acf.doAction('show', $settings);
+ },
+
+ close: function(){
+
+ // vars
+ var $settings = this.$el.children('.settings');
+
+ // close
+ $settings.slideUp();
+ this.$el.removeClass('open');
+
+ // action (close)
+ acf.doAction('close_field_object', this);
+ this.trigger('closeFieldObject');
+
+ // action (hide)
+ acf.doAction('hide', $settings);
+ },
+
+ serialize: function(){
+ return acf.serialize( this.$el, this.getInputName() );
+ },
+
+ save: function( type ){
+
+ // defaults
+ type = type || 'settings'; // meta, settings
+
+ // vars
+ var save = this.getProp('save');
+
+ // bail if already saving settings
+ if( save === 'settings' ) {
+ return;
+ }
+
+ // prop
+ this.setProp('save', type);
+
+ // debug
+ this.$el.attr('data-save', type);
+
+ // action
+ acf.doAction('save_field_object', this, type);
+ },
+
+ submit: function(){
+
+ // vars
+ var inputName = this.getInputName();
+ var save = this.get('save');
+
+ // close
+ if( this.isOpen() ) {
+ this.close();
+ }
+
+ // allow all inputs to save
+ if( save == 'settings' ) {
+ // do nothing
+
+ // allow only meta inputs to save
+ } else if( save == 'meta' ) {
+ this.$('> .settings [name^="' + inputName + '"]').remove();
+
+ // prevent all inputs from saving
+ } else {
+ this.$('[name^="' + inputName + '"]').remove();
+ }
+
+ // action
+ acf.doAction('submit_field_object', this);
+ },
+
+ onChange: function( e, $el ){
+
+ // save settings
+ this.save();
+
+ // action for 3rd party customization
+ acf.doAction('change_field_object', this);
+ },
+
+ onChanged: function( e, $el, name, value ){
+
+ // ignore 'save'
+ if( name == 'save' ) {
+ return;
+ }
+
+ // save meta
+ if( ['menu_order', 'parent'].indexOf(name) > -1 ) {
+ this.save('meta');
+
+ // save field
+ } else {
+ this.save();
+ }
+
+ // render
+ if( ['menu_order', 'label', 'required', 'name', 'type', 'key'].indexOf(name) > -1 ) {
+ this.render();
+ }
+
+ // action for 3rd party customization
+ acf.doAction('change_field_object_' + name, this, value);
+ },
+
+ onChangeLabel: function( e, $el ){
+
+ // set
+ var label = $el.val();
+ this.set('label', label);
+
+ // render name
+ if( this.prop('name') == '' ) {
+ var name = acf.applyFilters('generate_field_object_name', acf.strSanitize(label), this);
+ this.prop('name', name);
+ }
+ },
+
+ onChangeName: function( e, $el){
+
+ // set
+ var name = $el.val();
+ this.set('name', name);
+
+ // error
+ if( name.substr(0, 6) === 'field_' ) {
+ alert( acf.__('The string "field_" may not be used at the start of a field name') );
+ }
+ },
+
+ onChangeRequired: function( e, $el ){
+
+ // set
+ var required = $el.prop('checked') ? 1 : 0;
+ this.set('required', required);
+ },
+
+ delete: function( args ){
+
+ // defaults
+ args = acf.parseArgs(args, {
+ animate: true
+ });
+
+ // add to remove list
+ var id = this.prop('ID');
+
+ if( id ) {
+ var $input = $('#_acf_delete_fields');
+ var newVal = $input.val() + '|' + id;
+ $input.val( newVal );
+ }
+
+ // action
+ acf.doAction('delete_field_object', this);
+
+ // animate
+ if( args.animate ) {
+ this.removeAnimate();
+ } else {
+ this.remove();
+ }
+ },
+
+ onClickDelete: function( e, $el ){
+
+ // Bypass confirmation when holding down "shift" key.
+ if( e.shiftKey ) {
+ return this.delete();
+ }
+
+ // add class
+ this.$el.addClass('-hover');
+
+ // add tooltip
+ var tooltip = acf.newTooltip({
+ confirmRemove: true,
+ target: $el,
+ context: this,
+ confirm: function(){
+ this.delete();
+ },
+ cancel: function(){
+ this.$el.removeClass('-hover');
+ }
+ });
+ },
+
+ removeAnimate: function(){
+
+ // vars
+ var field = this;
+ var $list = this.$el.parent();
+ var $fields = acf.findFieldObjects({
+ sibling: this.$el
+ });
+
+ // remove
+ acf.remove({
+ target: this.$el,
+ endHeight: $fields.length ? 0 : 50,
+ complete: function(){
+ field.remove();
+ acf.doAction('removed_field_object', field, $list);
+ }
+ });
+
+ // action
+ acf.doAction('remove_field_object', field, $list);
+ },
+
+ duplicate: function(){
+
+ // vars
+ var newKey = acf.uniqid('field_');
+
+ // duplicate
+ var $newField = acf.duplicate({
+ target: this.$el,
+ search: this.get('id'),
+ replace: newKey,
+ });
+
+ // set new key
+ $newField.attr('data-key', newKey);
+
+ // get instance
+ var newField = acf.getFieldObject( $newField );
+
+ // open / close
+ if( this.isOpen() ) {
+ this.close();
+ } else {
+ newField.open();
+ }
+
+ // focus label
+ var $label = newField.$setting('label input');
+ setTimeout(function(){
+ $label.trigger('focus');
+ }, 251);
+
+ // update newField label / name
+ var label = newField.prop('label');
+ var name = newField.prop('name');
+ var end = name.split('_').pop();
+ var copy = acf.__('copy');
+
+ // increase suffix "1"
+ if( acf.isNumeric(end) ) {
+ var i = (end*1) + 1;
+ label = label.replace( end, i );
+ name = name.replace( end, i );
+
+ // increase suffix "(copy1)"
+ } else if( end.indexOf(copy) === 0 ) {
+ var i = end.replace(copy, '') * 1;
+ i = i ? i+1 : 2;
+
+ // replace
+ label = label.replace( end, copy + i );
+ name = name.replace( end, copy + i );
+
+ // add default "(copy)"
+ } else {
+ label += ' (' + copy + ')';
+ name += '_' + copy;
+ }
+
+ newField.prop('ID', 0);
+ newField.prop('label', label);
+ newField.prop('name', name);
+ newField.prop('key', newKey);
+
+ // action
+ acf.doAction('duplicate_field_object', this, newField);
+ acf.doAction('append_field_object', newField);
+ },
+
+ wipe: function(){
+
+ // vars
+ var prevId = this.get('id');
+ var prevKey = this.get('key');
+ var newKey = acf.uniqid('field_');
+
+ // rename
+ acf.rename({
+ target: this.$el,
+ search: prevId,
+ replace: newKey,
+ });
+
+ // data
+ this.set('id', newKey);
+ this.set('prevId', prevId);
+ this.set('prevKey', prevKey);
+
+ // props
+ this.prop('key', newKey);
+ this.prop('ID', 0);
+
+ // attr
+ this.$el.attr('data-key', newKey);
+ this.$el.attr('data-id', newKey);
+
+ // action
+ acf.doAction('wipe_field_object', this);
+ },
+
+ move: function(){
+
+ // helper
+ var hasChanged = function( field ){
+ return (field.get('save') == 'settings');
+ };
+
+ // vars
+ var changed = hasChanged(this);
+
+ // has sub fields changed
+ if( !changed ) {
+ acf.getFieldObjects({
+ parent: this.$el
+ }).map(function( field ){
+ changed = hasChanged(field) || field.changed;
+ });
+ }
+
+ // bail early if changed
+ if( changed ) {
+ alert( acf.__('This field cannot be moved until its changes have been saved') );
+ return;
+ }
+
+ // step 1.
+ var id = this.prop('ID');
+ var field = this;
+ var popup = false;
+ var step1 = function(){
+
+ // popup
+ popup = acf.newPopup({
+ title: acf.__('Move Custom Field'),
+ loading: true,
+ width: '300px'
+ });
+
+ // ajax
+ var ajaxData = {
+ action: 'acf/field_group/move_field',
+ field_id: id
+ };
+
+ // get HTML
+ $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxData),
+ type: 'post',
+ dataType: 'html',
+ success: step2
+ });
+ };
+
+ var step2 = function( html ){
+
+ // update popup
+ popup.loading(false);
+ popup.content(html);
+
+ // submit form
+ popup.on('submit', 'form', step3);
+ };
+
+ var step3 = function( e, $el ){
+
+ // prevent
+ e.preventDefault();
+
+ // disable
+ acf.startButtonLoading( popup.$('.button') );
+
+ // ajax
+ var ajaxData = {
+ action: 'acf/field_group/move_field',
+ field_id: id,
+ field_group_id: popup.$('select').val()
+ };
+
+ // get HTML
+ $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxData),
+ type: 'post',
+ dataType: 'html',
+ success: step4
+ });
+ };
+
+ var step4 = function( html ){
+
+ // update popup
+ popup.content(html);
+
+ // remove element
+ field.removeAnimate();
+ };
+
+ // start
+ step1();
+
+ },
+
+ onChangeType: function( e, $el ){
+
+ // clea previous timout
+ if( this.changeTimeout ) {
+ clearTimeout(this.changeTimeout);
+ }
+
+ // set new timeout
+ // - prevents changing type multiple times whilst user types in newType
+ this.changeTimeout = this.setTimeout(function(){
+ this.changeType( $el.val() );
+ }, 300);
+ },
+
+ changeType: function( newType ){
+
+ // vars
+ var prevType = this.prop('type');
+ var prevClass = acf.strSlugify( 'acf-field-object-' + prevType );
+ var newClass = acf.strSlugify( 'acf-field-object-' + newType );
+
+ // update props
+ this.$el.removeClass(prevClass).addClass(newClass);
+ this.$el.attr('data-type', newType);
+ this.$el.data('type', newType);
+
+ // abort XHR if this field is already loading AJAX data
+ if( this.has('xhr') ) {
+ this.get('xhr').abort();
+ }
+
+ // store settings
+ var $tbody = this.$('> .settings > table > tbody');
+ var $settings = $tbody.children('[data-setting="' + prevType + '"]');
+ this.set( 'settings-' + prevType, $settings );
+ $settings.detach();
+
+ // show settings
+ if( this.has('settings-' + newType) ) {
+ var $newSettings = this.get('settings-' + newType);
+ this.$setting('conditional_logic').before( $newSettings );
+ this.set('type', newType);
+ //this.refresh();
+ return;
+ }
+
+ // load settings
+ var $loading = $('
');
+ this.$setting('conditional_logic').before( $loading );
+
+ // ajax
+ var ajaxData = {
+ action: 'acf/field_group/render_field_settings',
+ field: this.serialize(),
+ prefix: this.getInputName()
+ };
+
+ // ajax
+ var xhr = $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxData),
+ type: 'post',
+ dataType: 'html',
+ context: this,
+ success: function( html ){
+
+ // bail early if no settings
+ if( !html ) return;
+
+ // append settings
+ $loading.after( html );
+
+ // events
+ acf.doAction('append', $tbody);
+ },
+ complete: function(){
+ // also triggered by xhr.abort();
+ $loading.remove();
+ this.set('type', newType);
+ //this.refresh();
+ }
+ });
+
+ // set
+ this.set('xhr', xhr);
+
+ },
+
+ updateParent: function(){
+
+ // vars
+ var ID = acf.get('post_id');
+
+ // check parent
+ var parent = this.getParent();
+ if( parent ) {
+ ID = parseInt(parent.prop('ID')) || parent.prop('key');
+ }
+
+ // update
+ this.prop('parent', ID);
+ }
+
+ });
+
})(jQuery);
+(function($, undefined){
+
+ /**
+ * mid
+ *
+ * Calculates the model ID for a field type
+ *
+ * @date 15/12/17
+ * @since 5.6.5
+ *
+ * @param string type
+ * @return string
+ */
+
+ var modelId = function( type ) {
+ return acf.strPascalCase( type || '' ) + 'FieldSetting';
+ };
+
+ /**
+ * registerFieldType
+ *
+ * description
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.registerFieldSetting = function( model ){
+ var proto = model.prototype;
+ var mid = modelId(proto.type + ' ' + proto.name);
+ this.models[ mid ] = model;
+ };
+
+ /**
+ * newField
+ *
+ * description
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.newFieldSetting = function( field ){
+
+ // vars
+ var type = field.get('setting') || '';
+ var name = field.get('name') || '';
+ var mid = modelId( type + ' ' + name );
+ var model = acf.models[ mid ] || null;
+
+ // bail ealry if no setting
+ if( model === null ) return false;
+
+ // instantiate
+ var setting = new model( field );
+
+ // return
+ return setting;
+ };
+
+ /**
+ * acf.getFieldSetting
+ *
+ * description
+ *
+ * @date 19/4/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.getFieldSetting = function( field ) {
+
+ // allow jQuery
+ if( field instanceof jQuery ) {
+ field = acf.getField(field);
+ }
+
+ // return
+ return field.setting;
+ };
+
+ /**
+ * settingsManager
+ *
+ * description
+ *
+ * @date 6/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var settingsManager = new acf.Model({
+ actions: {
+ 'new_field': 'onNewField'
+ },
+ onNewField: function( field ){
+ field.setting = acf.newFieldSetting( field );
+ }
+ });
+
+ /**
+ * acf.FieldSetting
+ *
+ * description
+ *
+ * @date 6/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.FieldSetting = acf.Model.extend({
-(function ($, undefined) {
- /**
- * mid
- *
- * Calculates the model ID for a field type
- *
- * @date 15/12/17
- * @since 5.6.5
- *
- * @param string type
- * @return string
- */
- var modelId = function (type) {
- return acf.strPascalCase(type || '') + 'FieldSetting';
- };
- /**
- * registerFieldType
- *
- * description
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.registerFieldSetting = function (model) {
- var proto = model.prototype;
- var mid = modelId(proto.type + ' ' + proto.name);
- this.models[mid] = model;
- };
- /**
- * newField
- *
- * description
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.newFieldSetting = function (field) {
- // vars
- var type = field.get('setting') || '';
- var name = field.get('name') || '';
- var mid = modelId(type + ' ' + name);
- var model = acf.models[mid] || null; // bail ealry if no setting
-
- if (model === null) return false; // instantiate
-
- var setting = new model(field); // return
-
- return setting;
- };
- /**
- * acf.getFieldSetting
- *
- * description
- *
- * @date 19/4/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.getFieldSetting = function (field) {
- // allow jQuery
- if (field instanceof jQuery) {
- field = acf.getField(field);
- } // return
-
-
- return field.setting;
- };
- /**
- * settingsManager
- *
- * description
- *
- * @date 6/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- var settingsManager = new acf.Model({
- actions: {
- 'new_field': 'onNewField'
- },
- onNewField: function (field) {
- field.setting = acf.newFieldSetting(field);
- }
- });
- /**
- * acf.FieldSetting
- *
- * description
- *
- * @date 6/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.FieldSetting = acf.Model.extend({
- field: false,
- type: '',
- name: '',
- wait: 'ready',
- eventScope: '.acf-field',
- events: {
- 'change': 'render'
- },
- setup: function (field) {
- // vars
- var $field = field.$el; // set props
-
- this.$el = $field;
- this.field = field;
- this.$fieldObject = $field.closest('.acf-field-object');
- this.fieldObject = acf.getFieldObject(this.$fieldObject); // inherit data
-
- $.extend(this.data, field.data);
- },
- initialize: function () {
- this.render();
- },
- render: function () {// do nothing
- }
- });
- /*
- * Date Picker
- *
- * This field type requires some extra logic for its settings
- *
- * @type function
- * @date 24/10/13
- * @since 5.0.0
- *
- * @param n/a
- * @return n/a
- */
-
- var DisplayFormatFieldSetting = acf.FieldSetting.extend({
- type: '',
- name: '',
- render: function () {
- var $input = this.$('input[type="radio"]:checked');
-
- if ($input.val() != 'other') {
- this.$('input[type="text"]').val($input.val());
- }
- }
- });
- var DatePickerDisplayFormatFieldSetting = DisplayFormatFieldSetting.extend({
- type: 'date_picker',
- name: 'display_format'
- });
- var DatePickerReturnFormatFieldSetting = DisplayFormatFieldSetting.extend({
- type: 'date_picker',
- name: 'return_format'
- });
- acf.registerFieldSetting(DatePickerDisplayFormatFieldSetting);
- acf.registerFieldSetting(DatePickerReturnFormatFieldSetting);
- /*
- * Date Time Picker
- *
- * This field type requires some extra logic for its settings
- *
- * @type function
- * @date 24/10/13
- * @since 5.0.0
- *
- * @param n/a
- * @return n/a
- */
-
- var DateTimePickerDisplayFormatFieldSetting = DisplayFormatFieldSetting.extend({
- type: 'date_time_picker',
- name: 'display_format'
- });
- var DateTimePickerReturnFormatFieldSetting = DisplayFormatFieldSetting.extend({
- type: 'date_time_picker',
- name: 'return_format'
- });
- acf.registerFieldSetting(DateTimePickerDisplayFormatFieldSetting);
- acf.registerFieldSetting(DateTimePickerReturnFormatFieldSetting);
- /*
- * Time Picker
- *
- * This field type requires some extra logic for its settings
- *
- * @type function
- * @date 24/10/13
- * @since 5.0.0
- *
- * @param n/a
- * @return n/a
- */
-
- var TimePickerDisplayFormatFieldSetting = DisplayFormatFieldSetting.extend({
- type: 'time_picker',
- name: 'display_format'
- });
- var TimePickerReturnFormatFieldSetting = DisplayFormatFieldSetting.extend({
- name: 'time_picker',
- name: 'return_format'
- });
- acf.registerFieldSetting(TimePickerDisplayFormatFieldSetting);
- acf.registerFieldSetting(TimePickerReturnFormatFieldSetting);
+ field: false,
+ type: '',
+ name: '',
+ wait: 'ready',
+ eventScope: '.acf-field',
+
+ events: {
+ 'change': 'render'
+ },
+
+ setup: function( field ){
+
+ // vars
+ var $field = field.$el;
+
+ // set props
+ this.$el = $field;
+ this.field = field;
+ this.$fieldObject = $field.closest('.acf-field-object');
+ this.fieldObject = acf.getFieldObject( this.$fieldObject );
+
+ // inherit data
+ $.extend(this.data, field.data);
+ },
+
+ initialize: function(){
+ this.render();
+ },
+
+ render: function(){
+ // do nothing
+ }
+ });
+
+ /*
+ * Date Picker
+ *
+ * This field type requires some extra logic for its settings
+ *
+ * @type function
+ * @date 24/10/13
+ * @since 5.0.0
+ *
+ * @param n/a
+ * @return n/a
+ */
+
+ var DisplayFormatFieldSetting = acf.FieldSetting.extend({
+ type: '',
+ name: '',
+ render: function(){
+ var $input = this.$('input[type="radio"]:checked');
+ if( $input.val() != 'other' ) {
+ this.$('input[type="text"]').val( $input.val() );
+ }
+ }
+ });
+
+ var DatePickerDisplayFormatFieldSetting = DisplayFormatFieldSetting.extend({
+ type: 'date_picker',
+ name: 'display_format'
+ });
+
+ var DatePickerReturnFormatFieldSetting = DisplayFormatFieldSetting.extend({
+ type: 'date_picker',
+ name: 'return_format'
+ });
+
+ acf.registerFieldSetting( DatePickerDisplayFormatFieldSetting );
+ acf.registerFieldSetting( DatePickerReturnFormatFieldSetting );
+
+ /*
+ * Date Time Picker
+ *
+ * This field type requires some extra logic for its settings
+ *
+ * @type function
+ * @date 24/10/13
+ * @since 5.0.0
+ *
+ * @param n/a
+ * @return n/a
+ */
+
+ var DateTimePickerDisplayFormatFieldSetting = DisplayFormatFieldSetting.extend({
+ type: 'date_time_picker',
+ name: 'display_format'
+ });
+
+ var DateTimePickerReturnFormatFieldSetting = DisplayFormatFieldSetting.extend({
+ type: 'date_time_picker',
+ name: 'return_format'
+ });
+
+ acf.registerFieldSetting( DateTimePickerDisplayFormatFieldSetting );
+ acf.registerFieldSetting( DateTimePickerReturnFormatFieldSetting );
+
+ /*
+ * Time Picker
+ *
+ * This field type requires some extra logic for its settings
+ *
+ * @type function
+ * @date 24/10/13
+ * @since 5.0.0
+ *
+ * @param n/a
+ * @return n/a
+ */
+
+ var TimePickerDisplayFormatFieldSetting = DisplayFormatFieldSetting.extend({
+ type: 'time_picker',
+ name: 'display_format'
+ });
+
+ var TimePickerReturnFormatFieldSetting = DisplayFormatFieldSetting.extend({
+ name: 'time_picker',
+ name: 'return_format'
+ });
+
+ acf.registerFieldSetting( TimePickerDisplayFormatFieldSetting );
+ acf.registerFieldSetting( TimePickerReturnFormatFieldSetting );
+
})(jQuery);
-
-(function ($, undefined) {
- /**
- * ConditionalLogicFieldSetting
- *
- * description
- *
- * @date 3/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- var ConditionalLogicFieldSetting = acf.FieldSetting.extend({
- type: '',
- name: 'conditional_logic',
- events: {
- 'change .conditions-toggle': 'onChangeToggle',
- 'click .add-conditional-group': 'onClickAddGroup',
- 'focus .condition-rule-field': 'onFocusField',
- 'change .condition-rule-field': 'onChangeField',
- 'change .condition-rule-operator': 'onChangeOperator',
- 'click .add-conditional-rule': 'onClickAdd',
- 'click .remove-conditional-rule': 'onClickRemove'
- },
- $rule: false,
- scope: function ($rule) {
- this.$rule = $rule;
- return this;
- },
- ruleData: function (name, value) {
- return this.$rule.data.apply(this.$rule, arguments);
- },
- $input: function (name) {
- return this.$rule.find('.condition-rule-' + name);
- },
- $td: function (name) {
- return this.$rule.find('td.' + name);
- },
- $toggle: function () {
- return this.$('.conditions-toggle');
- },
- $control: function () {
- return this.$('.rule-groups');
- },
- $groups: function () {
- return this.$('.rule-group');
- },
- $rules: function () {
- return this.$('.rule');
- },
- open: function () {
- var $div = this.$control();
- $div.show();
- acf.enable($div);
- },
- close: function () {
- var $div = this.$control();
- $div.hide();
- acf.disable($div);
- },
- render: function () {
- // show
- if (this.$toggle().prop('checked')) {
- this.renderRules();
- this.open(); // hide
- } else {
- this.close();
- }
- },
- renderRules: function () {
- // vars
- var self = this; // loop
-
- this.$rules().each(function () {
- self.renderRule($(this));
- });
- },
- renderRule: function ($rule) {
- this.scope($rule);
- this.renderField();
- this.renderOperator();
- this.renderValue();
- },
- renderField: function () {
- // vars
- var choices = [];
- var validFieldTypes = [];
- var cid = this.fieldObject.cid;
- var $select = this.$input('field'); // loop
-
- acf.getFieldObjects().map(function (fieldObject) {
- // vars
- var choice = {
- id: fieldObject.getKey(),
- text: fieldObject.getLabel()
- }; // bail early if is self
-
- if (fieldObject.cid === cid) {
- choice.text += acf.__('(this field)');
- choice.disabled = true;
- } // get selected field conditions
-
-
- var conditionTypes = acf.getConditionTypes({
- fieldType: fieldObject.getType()
- }); // bail early if no types
-
- if (!conditionTypes.length) {
- choice.disabled = true;
- } // calulate indents
-
-
- var indents = fieldObject.getParents().length;
- choice.text = '- '.repeat(indents) + choice.text; // append
-
- choices.push(choice);
- }); // allow for scenario where only one field exists
-
- if (!choices.length) {
- choices.push({
- id: '',
- text: acf.__('No toggle fields available')
- });
- } // render
-
-
- acf.renderSelect($select, choices); // set
-
- this.ruleData('field', $select.val());
- },
- renderOperator: function () {
- // bail early if no field selected
- if (!this.ruleData('field')) {
- return;
- } // vars
-
-
- var $select = this.$input('operator');
- var val = $select.val();
- var choices = []; // set saved value on first render
- // - this allows the 2nd render to correctly select an option
-
- if ($select.val() === null) {
- acf.renderSelect($select, [{
- id: this.ruleData('operator'),
- text: ''
- }]);
- } // get selected field
-
-
- var $field = acf.findFieldObject(this.ruleData('field'));
- var field = acf.getFieldObject($field); // get selected field conditions
-
- var conditionTypes = acf.getConditionTypes({
- fieldType: field.getType()
- }); // html
-
- conditionTypes.map(function (model) {
- choices.push({
- id: model.prototype.operator,
- text: model.prototype.label
- });
- }); // render
-
- acf.renderSelect($select, choices); // set
-
- this.ruleData('operator', $select.val());
- },
- renderValue: function () {
- // bail early if no field selected
- if (!this.ruleData('field') || !this.ruleData('operator')) {
- return;
- } // vars
-
-
- var $select = this.$input('value');
- var $td = this.$td('value');
- var val = $select.val(); // get selected field
-
- var $field = acf.findFieldObject(this.ruleData('field'));
- var field = acf.getFieldObject($field); // get selected field conditions
-
- var conditionTypes = acf.getConditionTypes({
- fieldType: field.getType(),
- operator: this.ruleData('operator')
- }); // html
-
- var conditionType = conditionTypes[0].prototype;
- var choices = conditionType.choices(field); // create html: array
-
- if (choices instanceof Array) {
- var $newSelect = $(' ');
- acf.renderSelect($newSelect, choices); // create html: string ( )
- } else {
- var $newSelect = $(choices);
- } // append
-
-
- $select.detach();
- $td.html($newSelect); // copy attrs
- // timeout needed to avoid browser bug where "disabled" attribute is not applied
-
- setTimeout(function () {
- ['class', 'name', 'id'].map(function (attr) {
- $newSelect.attr(attr, $select.attr(attr));
- });
- }, 0); // select existing value (if not a disabled input)
-
- if (!$newSelect.prop('disabled')) {
- acf.val($newSelect, val, true);
- } // set
-
-
- this.ruleData('value', $newSelect.val());
- },
- onChangeToggle: function () {
- this.render();
- },
- onClickAddGroup: function (e, $el) {
- this.addGroup();
- },
- addGroup: function () {
- // vars
- var $group = this.$('.rule-group:last'); // duplicate
-
- var $group2 = acf.duplicate($group); // update h4
-
- $group2.find('h4').text(acf.__('or')); // remove all tr's except the first one
-
- $group2.find('tr').not(':first').remove(); // save field
-
- this.fieldObject.save();
- },
- onFocusField: function (e, $el) {
- this.renderField();
- },
- onChangeField: function (e, $el) {
- // scope
- this.scope($el.closest('.rule')); // set data
-
- this.ruleData('field', $el.val()); // render
-
- this.renderOperator();
- this.renderValue();
- },
- onChangeOperator: function (e, $el) {
- // scope
- this.scope($el.closest('.rule')); // set data
-
- this.ruleData('operator', $el.val()); // render
-
- this.renderValue();
- },
- onClickAdd: function (e, $el) {
- // duplciate
- var $rule = acf.duplicate($el.closest('.rule')); // render
-
- this.renderRule($rule);
- },
- onClickRemove: function (e, $el) {
- // vars
- var $rule = $el.closest('.rule'); // save field
-
- this.fieldObject.save(); // remove group
-
- if ($rule.siblings('.rule').length == 0) {
- $rule.closest('.rule-group').remove();
- } // remove
-
-
- $rule.remove();
- }
- });
- acf.registerFieldSetting(ConditionalLogicFieldSetting);
- /**
- * conditionalLogicHelper
- *
- * description
- *
- * @date 20/4/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var conditionalLogicHelper = new acf.Model({
- actions: {
- 'duplicate_field_objects': 'onDuplicateFieldObjects'
- },
- onDuplicateFieldObjects: function (children, newField, prevField) {
- // vars
- var data = {};
- var $selects = $(); // reference change in key
-
- children.map(function (child) {
- // store reference of changed key
- data[child.get('prevKey')] = child.get('key'); // append condition select
-
- $selects = $selects.add(child.$('.condition-rule-field'));
- }); // loop
-
- $selects.each(function () {
- // vars
- var $select = $(this);
- var val = $select.val(); // bail early if val is not a ref key
-
- if (!val || !data[val]) {
- return;
- } // modify selected option
-
-
- $select.find('option:selected').attr('value', data[val]); // set new val
-
- $select.val(data[val]);
- });
- }
- });
+(function($, undefined){
+
+ /**
+ * ConditionalLogicFieldSetting
+ *
+ * description
+ *
+ * @date 3/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var ConditionalLogicFieldSetting = acf.FieldSetting.extend({
+ type: '',
+ name: 'conditional_logic',
+ events: {
+ 'change .conditions-toggle': 'onChangeToggle',
+ 'click .add-conditional-group': 'onClickAddGroup',
+ 'focus .condition-rule-field': 'onFocusField',
+ 'change .condition-rule-field': 'onChangeField',
+ 'change .condition-rule-operator': 'onChangeOperator',
+ 'click .add-conditional-rule': 'onClickAdd',
+ 'click .remove-conditional-rule': 'onClickRemove'
+ },
+
+ $rule: false,
+
+ scope: function( $rule ){
+ this.$rule = $rule;
+ return this;
+ },
+
+ ruleData: function( name, value ){
+ return this.$rule.data.apply( this.$rule, arguments );
+ },
+
+ $input: function( name ){
+ return this.$rule.find('.condition-rule-' + name);
+ },
+
+ $td: function( name ){
+ return this.$rule.find('td.' + name);
+ },
+
+ $toggle: function(){
+ return this.$('.conditions-toggle');
+ },
+
+ $control: function(){
+ return this.$('.rule-groups');
+ },
+
+ $groups: function(){
+ return this.$('.rule-group');
+ },
+
+ $rules: function(){
+ return this.$('.rule');
+ },
+
+ open: function(){
+ var $div = this.$control();
+ $div.show();
+ acf.enable( $div );
+ },
+
+ close: function(){
+ var $div = this.$control();
+ $div.hide();
+ acf.disable( $div );
+ },
+
+ render: function(){
+
+ // show
+ if( this.$toggle().prop('checked') ) {
+ this.renderRules();
+ this.open();
+
+ // hide
+ } else {
+ this.close();
+ }
+ },
+
+ renderRules: function(){
+
+ // vars
+ var self = this;
+
+ // loop
+ this.$rules().each(function(){
+ self.renderRule( $(this) );
+ });
+ },
+
+ renderRule: function( $rule ){
+ this.scope( $rule );
+ this.renderField();
+ this.renderOperator();
+ this.renderValue();
+ },
+
+ renderField: function(){
+
+ // vars
+ var choices = [];
+ var validFieldTypes = [];
+ var cid = this.fieldObject.cid;
+ var $select = this.$input('field');
+
+ // loop
+ acf.getFieldObjects().map(function( fieldObject ){
+
+ // vars
+ var choice = {
+ id: fieldObject.getKey(),
+ text: fieldObject.getLabel()
+ };
+
+ // bail early if is self
+ if( fieldObject.cid === cid ) {
+ choice.text += acf.__('(this field)');
+ choice.disabled = true;
+ }
+
+ // get selected field conditions
+ var conditionTypes = acf.getConditionTypes({
+ fieldType: fieldObject.getType()
+ });
+
+ // bail early if no types
+ if( !conditionTypes.length ) {
+ choice.disabled = true;
+ }
+
+ // calulate indents
+ var indents = fieldObject.getParents().length;
+ choice.text = '- '.repeat(indents) + choice.text;
+
+ // append
+ choices.push(choice);
+ });
+
+ // allow for scenario where only one field exists
+ if( !choices.length ) {
+ choices.push({
+ id: '',
+ text: acf.__('No toggle fields available'),
+ });
+ }
+
+ // render
+ acf.renderSelect( $select, choices );
+
+ // set
+ this.ruleData('field', $select.val());
+ },
+
+ renderOperator: function(){
+
+ // bail early if no field selected
+ if( !this.ruleData('field') ) {
+ return;
+ }
+
+ // vars
+ var $select = this.$input('operator');
+ var val = $select.val();
+ var choices = [];
+
+ // set saved value on first render
+ // - this allows the 2nd render to correctly select an option
+ if( $select.val() === null ) {
+ acf.renderSelect($select, [{
+ id: this.ruleData('operator'),
+ text: ''
+ }]);
+ }
+
+ // get selected field
+ var $field = acf.findFieldObject( this.ruleData('field') );
+ var field = acf.getFieldObject( $field );
+
+ // get selected field conditions
+ var conditionTypes = acf.getConditionTypes({
+ fieldType: field.getType()
+ });
+
+ // html
+ conditionTypes.map(function( model ){
+ choices.push({
+ id: model.prototype.operator,
+ text: model.prototype.label
+ });
+ });
+
+ // render
+ acf.renderSelect( $select, choices );
+
+ // set
+ this.ruleData('operator', $select.val());
+ },
+
+ renderValue: function(){
+
+ // bail early if no field selected
+ if( !this.ruleData('field') || !this.ruleData('operator') ) {
+ return;
+ }
+
+ // vars
+ var $select = this.$input('value');
+ var $td = this.$td('value');
+ var val = $select.val();
+
+ // get selected field
+ var $field = acf.findFieldObject( this.ruleData('field') );
+ var field = acf.getFieldObject( $field );
+
+ // get selected field conditions
+ var conditionTypes = acf.getConditionTypes({
+ fieldType: field.getType(),
+ operator: this.ruleData('operator')
+ });
+
+ // html
+ var conditionType = conditionTypes[0].prototype;
+ var choices = conditionType.choices( field );
+
+ // create html: array
+ if( choices instanceof Array ) {
+ var $newSelect = $(' ');
+ acf.renderSelect( $newSelect, choices );
+
+ // create html: string ( )
+ } else {
+ var $newSelect = $(choices);
+ }
+
+ // append
+ $select.detach();
+ $td.html( $newSelect );
+
+ // copy attrs
+ // timeout needed to avoid browser bug where "disabled" attribute is not applied
+ setTimeout(function(){
+ ['class', 'name', 'id'].map(function( attr ){
+ $newSelect.attr( attr, $select.attr(attr));
+ });
+ }, 0);
+
+ // select existing value (if not a disabled input)
+ if( !$newSelect.prop('disabled') ) {
+ acf.val( $newSelect, val, true );
+ }
+
+ // set
+ this.ruleData('value', $newSelect.val());
+ },
+
+ onChangeToggle: function(){
+ this.render();
+ },
+
+ onClickAddGroup: function( e, $el ){
+ this.addGroup();
+ },
+
+ addGroup: function(){
+
+ // vars
+ var $group = this.$('.rule-group:last');
+
+ // duplicate
+ var $group2 = acf.duplicate( $group );
+
+ // update h4
+ $group2.find('h4').text( acf.__('or') );
+
+ // remove all tr's except the first one
+ $group2.find('tr').not(':first').remove();
+
+ // save field
+ this.fieldObject.save();
+ },
+
+ onFocusField: function( e, $el ){
+ this.renderField();
+ },
+
+ onChangeField: function( e, $el ){
+
+ // scope
+ this.scope( $el.closest('.rule') );
+
+ // set data
+ this.ruleData('field', $el.val());
+
+ // render
+ this.renderOperator();
+ this.renderValue();
+ },
+
+ onChangeOperator: function( e, $el ){
+
+ // scope
+ this.scope( $el.closest('.rule') );
+
+ // set data
+ this.ruleData('operator', $el.val());
+
+ // render
+ this.renderValue();
+ },
+
+ onClickAdd: function( e, $el ){
+
+ // duplciate
+ var $rule = acf.duplicate( $el.closest('.rule') );
+
+ // render
+ this.renderRule( $rule );
+ },
+
+ onClickRemove: function( e, $el ){
+
+ // vars
+ var $rule = $el.closest('.rule');
+
+ // save field
+ this.fieldObject.save();
+
+ // remove group
+ if( $rule.siblings('.rule').length == 0 ) {
+ $rule.closest('.rule-group').remove();
+ }
+
+ // remove
+ $rule.remove();
+ }
+ });
+
+ acf.registerFieldSetting( ConditionalLogicFieldSetting );
+
+
+ /**
+ * conditionalLogicHelper
+ *
+ * description
+ *
+ * @date 20/4/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var conditionalLogicHelper = new acf.Model({
+ actions: {
+ 'duplicate_field_objects': 'onDuplicateFieldObjects',
+ },
+
+ onDuplicateFieldObjects: function( children, newField, prevField ){
+
+ // vars
+ var data = {};
+ var $selects = $();
+
+ // reference change in key
+ children.map(function( child ){
+
+ // store reference of changed key
+ data[ child.get('prevKey') ] = child.get('key');
+
+ // append condition select
+ $selects = $selects.add( child.$('.condition-rule-field') );
+ });
+
+ // loop
+ $selects.each(function(){
+
+ // vars
+ var $select = $(this);
+ var val = $select.val();
+
+ // bail early if val is not a ref key
+ if( !val || !data[val] ) {
+ return;
+ }
+
+ // modify selected option
+ $select.find('option:selected').attr('value', data[val]);
+
+ // set new val
+ $select.val( data[val] );
+
+ });
+ },
+ });
})(jQuery);
-
-(function ($, undefined) {
- /**
- * acf.findFieldObject
- *
- * Returns a single fieldObject $el for a given field key
- *
- * @date 1/2/18
- * @since 5.7.0
- *
- * @param string key The field key
- * @return jQuery
- */
- acf.findFieldObject = function (key) {
- return acf.findFieldObjects({
- key: key,
- limit: 1
- });
- };
- /**
- * acf.findFieldObjects
- *
- * Returns an array of fieldObject $el for the given args
- *
- * @date 1/2/18
- * @since 5.7.0
- *
- * @param object args
- * @return jQuery
- */
-
-
- acf.findFieldObjects = function (args) {
- // vars
- args = args || {};
- var selector = '.acf-field-object';
- var $fields = false; // args
-
- args = acf.parseArgs(args, {
- id: '',
- key: '',
- type: '',
- limit: false,
- list: null,
- parent: false,
- sibling: false,
- child: false
- }); // id
-
- if (args.id) {
- selector += '[data-id="' + args.id + '"]';
- } // key
-
-
- if (args.key) {
- selector += '[data-key="' + args.key + '"]';
- } // type
-
-
- if (args.type) {
- selector += '[data-type="' + args.type + '"]';
- } // query
-
-
- if (args.list) {
- $fields = args.list.children(selector);
- } else if (args.parent) {
- $fields = args.parent.find(selector);
- } else if (args.sibling) {
- $fields = args.sibling.siblings(selector);
- } else if (args.child) {
- $fields = args.child.parents(selector);
- } else {
- $fields = $(selector);
- } // limit
-
-
- if (args.limit) {
- $fields = $fields.slice(0, args.limit);
- } // return
-
-
- return $fields;
- };
- /**
- * acf.getFieldObject
- *
- * Returns a single fieldObject instance for a given $el|key
- *
- * @date 1/2/18
- * @since 5.7.0
- *
- * @param string|jQuery $field The field $el or key
- * @return jQuery
- */
-
-
- acf.getFieldObject = function ($field) {
- // allow key
- if (typeof $field === 'string') {
- $field = acf.findFieldObject($field);
- } // instantiate
-
-
- var field = $field.data('acf');
-
- if (!field) {
- field = acf.newFieldObject($field);
- } // return
-
-
- return field;
- };
- /**
- * acf.getFieldObjects
- *
- * Returns an array of fieldObject instances for the given args
- *
- * @date 1/2/18
- * @since 5.7.0
- *
- * @param object args
- * @return array
- */
-
-
- acf.getFieldObjects = function (args) {
- // query
- var $fields = acf.findFieldObjects(args); // loop
-
- var fields = [];
- $fields.each(function () {
- var field = acf.getFieldObject($(this));
- fields.push(field);
- }); // return
-
- return fields;
- };
- /**
- * acf.newFieldObject
- *
- * Initializes and returns a new FieldObject instance
- *
- * @date 1/2/18
- * @since 5.7.0
- *
- * @param jQuery $field The field $el
- * @return object
- */
-
-
- acf.newFieldObject = function ($field) {
- // instantiate
- var field = new acf.FieldObject($field); // action
-
- acf.doAction('new_field_object', field); // return
-
- return field;
- };
- /**
- * actionManager
- *
- * description
- *
- * @date 15/12/17
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- var eventManager = new acf.Model({
- priority: 5,
- initialize: function () {
- // actions
- var actions = ['prepare', 'ready', 'append', 'remove']; // loop
-
- actions.map(function (action) {
- this.addFieldActions(action);
- }, this);
- },
- addFieldActions: function (action) {
- // vars
- var pluralAction = action + '_field_objects'; // ready_field_objects
-
- var singleAction = action + '_field_object'; // ready_field_object
-
- var singleEvent = action + 'FieldObject'; // readyFieldObject
- // global action
-
- var callback = function ($el
- /*, arg1, arg2, etc*/
- ) {
- // vars
- var fieldObjects = acf.getFieldObjects({
- parent: $el
- }); // call plural
-
- if (fieldObjects.length) {
- /// get args [$el, arg1]
- var args = acf.arrayArgs(arguments); // modify args [pluralAction, fields, arg1]
-
- args.splice(0, 1, pluralAction, fieldObjects);
- acf.doAction.apply(null, args);
- }
- }; // plural action
-
-
- var pluralCallback = function (fieldObjects
- /*, arg1, arg2, etc*/
- ) {
- /// get args [fields, arg1]
- var args = acf.arrayArgs(arguments); // modify args [singleAction, fields, arg1]
-
- args.unshift(singleAction); // loop
-
- fieldObjects.map(function (fieldObject) {
- // modify args [singleAction, field, arg1]
- args[1] = fieldObject;
- acf.doAction.apply(null, args);
- });
- }; // single action
-
-
- var singleCallback = function (fieldObject
- /*, arg1, arg2, etc*/
- ) {
- /// get args [$field, arg1]
- var args = acf.arrayArgs(arguments); // modify args [singleAction, $field, arg1]
-
- args.unshift(singleAction); // action variations (ready_field/type=image)
-
- var variations = ['type', 'name', 'key'];
- variations.map(function (variation) {
- args[0] = singleAction + '/' + variation + '=' + fieldObject.get(variation);
- acf.doAction.apply(null, args);
- }); // modify args [arg1]
-
- args.splice(0, 2); // event
-
- fieldObject.trigger(singleEvent, args);
- }; // add actions
-
-
- acf.addAction(action, callback, 5);
- acf.addAction(pluralAction, pluralCallback, 5);
- acf.addAction(singleAction, singleCallback, 5);
- }
- });
- /**
- * fieldManager
- *
- * description
- *
- * @date 4/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var fieldManager = new acf.Model({
- id: 'fieldManager',
- events: {
- 'submit #post': 'onSubmit',
- 'mouseenter .acf-field-list': 'onHoverSortable',
- 'click .add-field': 'onClickAdd'
- },
- actions: {
- 'removed_field_object': 'onRemovedField',
- 'sortstop_field_object': 'onReorderField',
- 'delete_field_object': 'onDeleteField',
- 'change_field_object_type': 'onChangeFieldType',
- 'duplicate_field_object': 'onDuplicateField'
- },
- onSubmit: function (e, $el) {
- // vars
- var fields = acf.getFieldObjects(); // loop
-
- fields.map(function (field) {
- field.submit();
- });
- },
- setFieldMenuOrder: function (field) {
- this.renderFields(field.$el.parent());
- },
- onHoverSortable: function (e, $el) {
- // bail early if already sortable
- if ($el.hasClass('ui-sortable')) return; // sortable
-
- $el.sortable({
- handle: '.acf-sortable-handle',
- connectWith: '.acf-field-list',
- start: function (e, ui) {
- var field = acf.getFieldObject(ui.item);
- ui.placeholder.height(ui.item.height());
- acf.doAction('sortstart_field_object', field, $el);
- },
- update: function (e, ui) {
- var field = acf.getFieldObject(ui.item);
- acf.doAction('sortstop_field_object', field, $el);
- }
- });
- },
- onRemovedField: function (field, $list) {
- this.renderFields($list);
- },
- onReorderField: function (field, $list) {
- field.updateParent();
- this.renderFields($list);
- },
- onDeleteField: function (field) {
- // delete children
- field.getFields().map(function (child) {
- child.delete({
- animate: false
- });
- });
- },
- onChangeFieldType: function (field) {// this caused sub fields to disapear if changing type back...
- //this.onDeleteField( field );
- },
- onDuplicateField: function (field, newField) {
- // check for children
- var children = newField.getFields();
-
- if (children.length) {
- // loop
- children.map(function (child) {
- // wipe field
- child.wipe(); // update parent
-
- child.updateParent();
- }); // action
-
- acf.doAction('duplicate_field_objects', children, newField, field);
- } // set menu order
-
-
- this.setFieldMenuOrder(newField);
- },
- renderFields: function ($list) {
- // vars
- var fields = acf.getFieldObjects({
- list: $list
- }); // no fields
-
- if (!fields.length) {
- $list.addClass('-empty');
- return;
- } // has fields
-
-
- $list.removeClass('-empty'); // prop
-
- fields.map(function (field, i) {
- field.prop('menu_order', i);
- });
- },
- onClickAdd: function (e, $el) {
- var $list = $el.closest('.acf-tfoot').siblings('.acf-field-list');
- this.addField($list);
- },
- addField: function ($list) {
- // vars
- var html = $('#tmpl-acf-field').html();
- var $el = $(html);
- var prevId = $el.data('id');
- var newKey = acf.uniqid('field_'); // duplicate
-
- var $newField = acf.duplicate({
- target: $el,
- search: prevId,
- replace: newKey,
- append: function ($el, $el2) {
- $list.append($el2);
- }
- }); // get instance
-
- var newField = acf.getFieldObject($newField); // props
-
- newField.prop('key', newKey);
- newField.prop('ID', 0);
- newField.prop('label', '');
- newField.prop('name', ''); // attr
-
- $newField.attr('data-key', newKey);
- $newField.attr('data-id', newKey); // update parent prop
-
- newField.updateParent(); // focus label
-
- var $label = newField.$input('label');
- setTimeout(function () {
- $label.trigger('focus');
- }, 251); // open
-
- newField.open(); // set menu order
-
- this.renderFields($list); // action
-
- acf.doAction('add_field_object', newField);
- acf.doAction('append_field_object', newField);
- }
- });
+(function($, undefined){
+
+ /**
+ * acf.findFieldObject
+ *
+ * Returns a single fieldObject $el for a given field key
+ *
+ * @date 1/2/18
+ * @since 5.7.0
+ *
+ * @param string key The field key
+ * @return jQuery
+ */
+
+ acf.findFieldObject = function( key ){
+ return acf.findFieldObjects({
+ key: key,
+ limit: 1
+ });
+ };
+
+ /**
+ * acf.findFieldObjects
+ *
+ * Returns an array of fieldObject $el for the given args
+ *
+ * @date 1/2/18
+ * @since 5.7.0
+ *
+ * @param object args
+ * @return jQuery
+ */
+
+ acf.findFieldObjects = function( args ){
+
+ // vars
+ args = args || {};
+ var selector = '.acf-field-object';
+ var $fields = false;
+
+ // args
+ args = acf.parseArgs(args, {
+ id: '',
+ key: '',
+ type: '',
+ limit: false,
+ list: null,
+ parent: false,
+ sibling: false,
+ child: false,
+ });
+
+ // id
+ if( args.id ) {
+ selector += '[data-id="' + args.id + '"]';
+ }
+
+ // key
+ if( args.key ) {
+ selector += '[data-key="' + args.key + '"]';
+ }
+
+ // type
+ if( args.type ) {
+ selector += '[data-type="' + args.type + '"]';
+ }
+
+ // query
+ if( args.list ) {
+ $fields = args.list.children( selector );
+ } else if( args.parent ) {
+ $fields = args.parent.find( selector );
+ } else if( args.sibling ) {
+ $fields = args.sibling.siblings( selector );
+ } else if( args.child ) {
+ $fields = args.child.parents( selector );
+ } else {
+ $fields = $( selector );
+ }
+
+ // limit
+ if( args.limit ) {
+ $fields = $fields.slice( 0, args.limit );
+ }
+
+ // return
+ return $fields;
+ };
+
+ /**
+ * acf.getFieldObject
+ *
+ * Returns a single fieldObject instance for a given $el|key
+ *
+ * @date 1/2/18
+ * @since 5.7.0
+ *
+ * @param string|jQuery $field The field $el or key
+ * @return jQuery
+ */
+
+ acf.getFieldObject = function( $field ){
+
+ // allow key
+ if( typeof $field === 'string' ) {
+ $field = acf.findFieldObject( $field );
+ }
+
+ // instantiate
+ var field = $field.data('acf');
+ if( !field ) {
+ field = acf.newFieldObject( $field );
+ }
+
+ // return
+ return field;
+ };
+
+ /**
+ * acf.getFieldObjects
+ *
+ * Returns an array of fieldObject instances for the given args
+ *
+ * @date 1/2/18
+ * @since 5.7.0
+ *
+ * @param object args
+ * @return array
+ */
+
+ acf.getFieldObjects = function( args ){
+
+ // query
+ var $fields = acf.findFieldObjects( args );
+
+ // loop
+ var fields = [];
+ $fields.each(function(){
+ var field = acf.getFieldObject( $(this) );
+ fields.push( field );
+ });
+
+ // return
+ return fields;
+ };
+
+ /**
+ * acf.newFieldObject
+ *
+ * Initializes and returns a new FieldObject instance
+ *
+ * @date 1/2/18
+ * @since 5.7.0
+ *
+ * @param jQuery $field The field $el
+ * @return object
+ */
+
+ acf.newFieldObject = function( $field ){
+
+ // instantiate
+ var field = new acf.FieldObject( $field );
+
+ // action
+ acf.doAction('new_field_object', field);
+
+ // return
+ return field;
+ };
+
+ /**
+ * actionManager
+ *
+ * description
+ *
+ * @date 15/12/17
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var eventManager = new acf.Model({
+
+ priority: 5,
+
+ initialize: function(){
+
+ // actions
+ var actions = [
+ 'prepare',
+ 'ready',
+ 'append',
+ 'remove'
+ ];
+
+ // loop
+ actions.map(function( action ){
+ this.addFieldActions( action );
+ }, this);
+ },
+
+ addFieldActions: function( action ){
+
+ // vars
+ var pluralAction = action + '_field_objects'; // ready_field_objects
+ var singleAction = action + '_field_object'; // ready_field_object
+ var singleEvent = action + 'FieldObject'; // readyFieldObject
+
+ // global action
+ var callback = function( $el /*, arg1, arg2, etc*/ ){
+
+ // vars
+ var fieldObjects = acf.getFieldObjects({ parent: $el });
+
+ // call plural
+ if( fieldObjects.length ) {
+
+ /// get args [$el, arg1]
+ var args = acf.arrayArgs( arguments );
+
+ // modify args [pluralAction, fields, arg1]
+ args.splice(0, 1, pluralAction, fieldObjects);
+ acf.doAction.apply(null, args);
+ }
+ };
+
+ // plural action
+ var pluralCallback = function( fieldObjects /*, arg1, arg2, etc*/ ){
+
+ /// get args [fields, arg1]
+ var args = acf.arrayArgs( arguments );
+
+ // modify args [singleAction, fields, arg1]
+ args.unshift(singleAction);
+
+ // loop
+ fieldObjects.map(function( fieldObject ){
+
+ // modify args [singleAction, field, arg1]
+ args[1] = fieldObject;
+ acf.doAction.apply(null, args);
+ });
+ };
+
+ // single action
+ var singleCallback = function( fieldObject /*, arg1, arg2, etc*/ ){
+
+ /// get args [$field, arg1]
+ var args = acf.arrayArgs( arguments );
+
+ // modify args [singleAction, $field, arg1]
+ args.unshift(singleAction);
+
+ // action variations (ready_field/type=image)
+ var variations = ['type', 'name', 'key'];
+ variations.map(function( variation ){
+ args[0] = singleAction + '/' + variation + '=' + fieldObject.get(variation);
+ acf.doAction.apply(null, args);
+ });
+
+ // modify args [arg1]
+ args.splice(0, 2);
+
+ // event
+ fieldObject.trigger(singleEvent, args);
+ };
+
+ // add actions
+ acf.addAction(action, callback, 5);
+ acf.addAction(pluralAction, pluralCallback, 5);
+ acf.addAction(singleAction, singleCallback, 5);
+
+ }
+ });
+
+ /**
+ * fieldManager
+ *
+ * description
+ *
+ * @date 4/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var fieldManager = new acf.Model({
+
+ id: 'fieldManager',
+
+ events: {
+ 'submit #post': 'onSubmit',
+ 'mouseenter .acf-field-list': 'onHoverSortable',
+ 'click .add-field': 'onClickAdd',
+ },
+
+ actions: {
+ 'removed_field_object': 'onRemovedField',
+ 'sortstop_field_object': 'onReorderField',
+ 'delete_field_object': 'onDeleteField',
+ 'change_field_object_type': 'onChangeFieldType',
+ 'duplicate_field_object': 'onDuplicateField'
+ },
+
+ onSubmit: function( e, $el ){
+
+ // vars
+ var fields = acf.getFieldObjects();
+
+ // loop
+ fields.map(function( field ){
+ field.submit();
+ });
+ },
+
+ setFieldMenuOrder: function( field ){
+ this.renderFields( field.$el.parent() );
+ },
+
+ onHoverSortable: function( e, $el ){
+
+ // bail early if already sortable
+ if( $el.hasClass('ui-sortable') ) return;
+
+ // sortable
+ $el.sortable({
+ handle: '.acf-sortable-handle',
+ connectWith: '.acf-field-list',
+ start: function( e, ui ){
+ var field = acf.getFieldObject( ui.item );
+ ui.placeholder.height( ui.item.height() );
+ acf.doAction('sortstart_field_object', field, $el);
+ },
+ update: function( e, ui ){
+ var field = acf.getFieldObject( ui.item );
+ acf.doAction('sortstop_field_object', field, $el);
+ }
+ });
+ },
+
+ onRemovedField: function( field, $list ){
+ this.renderFields( $list );
+ },
+
+ onReorderField: function( field, $list ){
+ field.updateParent();
+ this.renderFields( $list );
+ },
+
+ onDeleteField: function( field ){
+
+ // delete children
+ field.getFields().map(function( child ){
+ child.delete({ animate: false });
+ });
+ },
+
+ onChangeFieldType: function( field ){
+ // this caused sub fields to disapear if changing type back...
+ //this.onDeleteField( field );
+ },
+
+ onDuplicateField: function( field, newField ){
+
+ // check for children
+ var children = newField.getFields();
+ if( children.length ) {
+
+ // loop
+ children.map(function( child ){
+
+ // wipe field
+ child.wipe();
+
+ // update parent
+ child.updateParent();
+ });
+
+ // action
+ acf.doAction('duplicate_field_objects', children, newField, field);
+ }
+
+ // set menu order
+ this.setFieldMenuOrder( newField );
+ },
+
+ renderFields: function( $list ){
+
+ // vars
+ var fields = acf.getFieldObjects({
+ list: $list
+ });
+
+ // no fields
+ if( !fields.length ) {
+ $list.addClass('-empty');
+ return;
+ }
+
+ // has fields
+ $list.removeClass('-empty');
+
+ // prop
+ fields.map(function( field, i ){
+ field.prop('menu_order', i);
+ });
+ },
+
+ onClickAdd: function( e, $el ){
+ var $list = $el.closest('.acf-tfoot').siblings('.acf-field-list');
+ this.addField( $list );
+ },
+
+ addField: function( $list ){
+
+ // vars
+ var html = $('#tmpl-acf-field').html();
+ var $el = $(html);
+ var prevId = $el.data('id');
+ var newKey = acf.uniqid('field_');
+
+ // duplicate
+ var $newField = acf.duplicate({
+ target: $el,
+ search: prevId,
+ replace: newKey,
+ append: function( $el, $el2 ){
+ $list.append( $el2 );
+ }
+ });
+
+ // get instance
+ var newField = acf.getFieldObject( $newField );
+
+ // props
+ newField.prop('key', newKey);
+ newField.prop('ID', 0);
+ newField.prop('label', '');
+ newField.prop('name', '');
+
+ // attr
+ $newField.attr('data-key', newKey);
+ $newField.attr('data-id', newKey);
+
+ // update parent prop
+ newField.updateParent();
+
+ // focus label
+ var $label = newField.$input('label');
+ setTimeout(function(){
+ $label.trigger('focus');
+ }, 251);
+
+ // open
+ newField.open();
+
+ // set menu order
+ this.renderFields( $list );
+
+ // action
+ acf.doAction('add_field_object', newField);
+ acf.doAction('append_field_object', newField);
+ }
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- /**
- * locationManager
- *
- * Field group location rules functionality
- *
- * @date 15/12/17
- * @since 5.7.0
- *
- * @param void
- * @return void
- */
- var locationManager = new acf.Model({
- id: 'locationManager',
- wait: 'ready',
- events: {
- 'click .add-location-rule': 'onClickAddRule',
- 'click .add-location-group': 'onClickAddGroup',
- 'click .remove-location-rule': 'onClickRemoveRule',
- 'change .refresh-location-rule': 'onChangeRemoveRule'
- },
- initialize: function () {
- this.$el = $('#acf-field-group-locations');
- },
- onClickAddRule: function (e, $el) {
- this.addRule($el.closest('tr'));
- },
- onClickRemoveRule: function (e, $el) {
- this.removeRule($el.closest('tr'));
- },
- onChangeRemoveRule: function (e, $el) {
- this.changeRule($el.closest('tr'));
- },
- onClickAddGroup: function (e, $el) {
- this.addGroup();
- },
- addRule: function ($tr) {
- acf.duplicate($tr);
- },
- removeRule: function ($tr) {
- if ($tr.siblings('tr').length == 0) {
- $tr.closest('.rule-group').remove();
- } else {
- $tr.remove();
- }
- },
- changeRule: function ($rule) {
- // vars
- var $group = $rule.closest('.rule-group');
- var prefix = $rule.find('td.param select').attr('name').replace('[param]', ''); // ajaxdata
-
- var ajaxdata = {};
- ajaxdata.action = 'acf/field_group/render_location_rule';
- ajaxdata.rule = acf.serialize($rule, prefix);
- ajaxdata.rule.id = $rule.data('id');
- ajaxdata.rule.group = $group.data('id'); // temp disable
-
- acf.disable($rule.find('td.value')); // ajax
-
- $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxdata),
- type: 'post',
- dataType: 'html',
- success: function (html) {
- if (!html) return;
- $rule.replaceWith(html);
- }
- });
- },
- addGroup: function () {
- // vars
- var $group = this.$('.rule-group:last'); // duplicate
-
- $group2 = acf.duplicate($group); // update h4
-
- $group2.find('h4').text(acf.__('or')); // remove all tr's except the first one
-
- $group2.find('tr').not(':first').remove();
- }
- });
+(function($, undefined){
+
+ /**
+ * locationManager
+ *
+ * Field group location rules functionality
+ *
+ * @date 15/12/17
+ * @since 5.7.0
+ *
+ * @param void
+ * @return void
+ */
+
+ var locationManager = new acf.Model({
+
+ id: 'locationManager',
+ wait: 'ready',
+
+ events: {
+ 'click .add-location-rule': 'onClickAddRule',
+ 'click .add-location-group': 'onClickAddGroup',
+ 'click .remove-location-rule': 'onClickRemoveRule',
+ 'change .refresh-location-rule': 'onChangeRemoveRule'
+ },
+
+ initialize: function(){
+ this.$el = $('#acf-field-group-locations');
+ },
+
+ onClickAddRule: function( e, $el ){
+ this.addRule( $el.closest('tr') );
+ },
+
+ onClickRemoveRule: function( e, $el ){
+ this.removeRule( $el.closest('tr') );
+ },
+
+ onChangeRemoveRule: function( e, $el ){
+ this.changeRule( $el.closest('tr') );
+ },
+
+ onClickAddGroup: function( e, $el ){
+ this.addGroup();
+ },
+
+ addRule: function( $tr ){
+ acf.duplicate( $tr );
+ },
+
+ removeRule: function( $tr ){
+ if( $tr.siblings('tr').length == 0 ) {
+ $tr.closest('.rule-group').remove();
+ } else {
+ $tr.remove();
+ }
+ },
+
+ changeRule: function( $rule ){
+
+ // vars
+ var $group = $rule.closest('.rule-group');
+ var prefix = $rule.find('td.param select').attr('name').replace('[param]', '');
+
+ // ajaxdata
+ var ajaxdata = {};
+ ajaxdata.action = 'acf/field_group/render_location_rule';
+ ajaxdata.rule = acf.serialize( $rule, prefix );
+ ajaxdata.rule.id = $rule.data('id');
+ ajaxdata.rule.group = $group.data('id');
+
+ // temp disable
+ acf.disable( $rule.find('td.value') );
+
+ // ajax
+ $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxdata),
+ type: 'post',
+ dataType: 'html',
+ success: function( html ){
+ if( !html ) return;
+ $rule.replaceWith( html );
+ }
+ });
+ },
+
+ addGroup: function(){
+
+ // vars
+ var $group = this.$('.rule-group:last');
+
+ // duplicate
+ $group2 = acf.duplicate( $group );
+
+ // update h4
+ $group2.find('h4').text( acf.__('or') );
+
+ // remove all tr's except the first one
+ $group2.find('tr').not(':first').remove();
+ }
+ });
+
})(jQuery);
+(function($, undefined){
+
+ var _acf = acf.getCompatibility( acf );
+
+ /**
+ * fieldGroupCompatibility
+ *
+ * Compatibility layer for extinct acf.field_group
+ *
+ * @date 15/12/17
+ * @since 5.7.0
+ *
+ * @param void
+ * @return void
+ */
+
+ _acf.field_group = {
+
+ save_field: function( $field, type ){
+ type = (type !== undefined) ? type : 'settings';
+ acf.getFieldObject( $field ).save( type );
+ },
+
+ delete_field: function( $field, animate ){
+ animate = (animate !== undefined) ? animate : true;
+ acf.getFieldObject( $field ).delete({
+ animate: animate
+ });
+ },
+
+ update_field_meta: function( $field, name, value ){
+ acf.getFieldObject( $field ).prop( name, value );
+ },
+
+ delete_field_meta: function( $field, name ){
+ acf.getFieldObject( $field ).prop( name, null );
+ }
+ };
+
+ /**
+ * fieldGroupCompatibility.field_object
+ *
+ * Compatibility layer for extinct acf.field_group.field_object
+ *
+ * @date 15/12/17
+ * @since 5.7.0
+ *
+ * @param void
+ * @return void
+ */
+
+ _acf.field_group.field_object = acf.model.extend({
+
+ // vars
+ type: '',
+ o: {},
+ $field: null,
+ $settings: null,
+
+ tag: function( tag ) {
+
+ // vars
+ var type = this.type;
+
+
+ // explode, add 'field' and implode
+ // - open => open_field
+ // - change_type => change_field_type
+ var tags = tag.split('_');
+ tags.splice(1, 0, 'field');
+ tag = tags.join('_');
+
+
+ // add type
+ if( type ) {
+ tag += '/type=' + type;
+ }
+
+
+ // return
+ return tag;
+
+ },
+
+ selector: function(){
+
+ // vars
+ var selector = '.acf-field-object';
+ var type = this.type;
+
-(function ($, undefined) {
- var _acf = acf.getCompatibility(acf);
- /**
- * fieldGroupCompatibility
- *
- * Compatibility layer for extinct acf.field_group
- *
- * @date 15/12/17
- * @since 5.7.0
- *
- * @param void
- * @return void
- */
-
-
- _acf.field_group = {
- save_field: function ($field, type) {
- type = type !== undefined ? type : 'settings';
- acf.getFieldObject($field).save(type);
- },
- delete_field: function ($field, animate) {
- animate = animate !== undefined ? animate : true;
- acf.getFieldObject($field).delete({
- animate: animate
- });
- },
- update_field_meta: function ($field, name, value) {
- acf.getFieldObject($field).prop(name, value);
- },
- delete_field_meta: function ($field, name) {
- acf.getFieldObject($field).prop(name, null);
- }
- };
- /**
- * fieldGroupCompatibility.field_object
- *
- * Compatibility layer for extinct acf.field_group.field_object
- *
- * @date 15/12/17
- * @since 5.7.0
- *
- * @param void
- * @return void
- */
-
- _acf.field_group.field_object = acf.model.extend({
- // vars
- type: '',
- o: {},
- $field: null,
- $settings: null,
- tag: function (tag) {
- // vars
- var type = this.type; // explode, add 'field' and implode
- // - open => open_field
- // - change_type => change_field_type
-
- var tags = tag.split('_');
- tags.splice(1, 0, 'field');
- tag = tags.join('_'); // add type
-
- if (type) {
- tag += '/type=' + type;
- } // return
-
-
- return tag;
- },
- selector: function () {
- // vars
- var selector = '.acf-field-object';
- var type = this.type; // add type
-
- if (type) {
- selector += '-' + type;
- selector = acf.str_replace('_', '-', selector);
- } // return
-
-
- return selector;
- },
- _add_action: function (name, callback) {
- // vars
- var model = this; // add action
-
- acf.add_action(this.tag(name), function ($field) {
- // focus
- model.set('$field', $field); // callback
-
- model[callback].apply(model, arguments);
- });
- },
- _add_filter: function (name, callback) {
- // vars
- var model = this; // add action
-
- acf.add_filter(this.tag(name), function ($field) {
- // focus
- model.set('$field', $field); // callback
-
- model[callback].apply(model, arguments);
- });
- },
- _add_event: function (name, callback) {
- // vars
- var model = this;
- var event = name.substr(0, name.indexOf(' '));
- var selector = name.substr(name.indexOf(' ') + 1);
- var context = this.selector(); // add event
-
- $(document).on(event, context + ' ' + selector, function (e) {
- // append $el to event object
- e.$el = $(this);
- e.$field = e.$el.closest('.acf-field-object'); // focus
-
- model.set('$field', e.$field); // callback
-
- model[callback].apply(model, [e]);
- });
- },
- _set_$field: function () {
- // vars
- this.o = this.$field.data(); // els
-
- this.$settings = this.$field.find('> .settings > table > tbody'); // focus
-
- this.focus();
- },
- focus: function () {// do nothing
- },
- setting: function (name) {
- return this.$settings.find('> .acf-field-setting-' + name);
- }
- });
- /*
- * field
- *
- * This model fires actions and filters for registered fields
- *
- * @type function
- * @date 21/02/2014
- * @since 3.5.1
- *
- * @param n/a
- * @return n/a
- */
-
- var actionManager = new acf.Model({
- actions: {
- 'open_field_object': 'onOpenFieldObject',
- 'close_field_object': 'onCloseFieldObject',
- 'add_field_object': 'onAddFieldObject',
- 'duplicate_field_object': 'onDuplicateFieldObject',
- 'delete_field_object': 'onDeleteFieldObject',
- 'change_field_object_type': 'onChangeFieldObjectType',
- 'change_field_object_label': 'onChangeFieldObjectLabel',
- 'change_field_object_name': 'onChangeFieldObjectName',
- 'change_field_object_parent': 'onChangeFieldObjectParent',
- 'sortstop_field_object': 'onChangeFieldObjectParent'
- },
- onOpenFieldObject: function (field) {
- acf.doAction('open_field', field.$el);
- acf.doAction('open_field/type=' + field.get('type'), field.$el);
- acf.doAction('render_field_settings', field.$el);
- acf.doAction('render_field_settings/type=' + field.get('type'), field.$el);
- },
- onCloseFieldObject: function (field) {
- acf.doAction('close_field', field.$el);
- acf.doAction('close_field/type=' + field.get('type'), field.$el);
- },
- onAddFieldObject: function (field) {
- acf.doAction('add_field', field.$el);
- acf.doAction('add_field/type=' + field.get('type'), field.$el);
- },
- onDuplicateFieldObject: function (field) {
- acf.doAction('duplicate_field', field.$el);
- acf.doAction('duplicate_field/type=' + field.get('type'), field.$el);
- },
- onDeleteFieldObject: function (field) {
- acf.doAction('delete_field', field.$el);
- acf.doAction('delete_field/type=' + field.get('type'), field.$el);
- },
- onChangeFieldObjectType: function (field) {
- acf.doAction('change_field_type', field.$el);
- acf.doAction('change_field_type/type=' + field.get('type'), field.$el);
- acf.doAction('render_field_settings', field.$el);
- acf.doAction('render_field_settings/type=' + field.get('type'), field.$el);
- },
- onChangeFieldObjectLabel: function (field) {
- acf.doAction('change_field_label', field.$el);
- acf.doAction('change_field_label/type=' + field.get('type'), field.$el);
- },
- onChangeFieldObjectName: function (field) {
- acf.doAction('change_field_name', field.$el);
- acf.doAction('change_field_name/type=' + field.get('type'), field.$el);
- },
- onChangeFieldObjectParent: function (field) {
- acf.doAction('update_field_parent', field.$el);
- }
- });
+ // add type
+ if( type ) {
+ selector += '-' + type;
+ selector = acf.str_replace('_', '-', selector);
+ }
+
+
+ // return
+ return selector;
+
+ },
+
+ _add_action: function( name, callback ) {
+
+ // vars
+ var model = this;
+
+
+ // add action
+ acf.add_action( this.tag(name), function( $field ){
+
+ // focus
+ model.set('$field', $field);
+
+
+ // callback
+ model[ callback ].apply(model, arguments);
+
+ });
+
+ },
+
+ _add_filter: function( name, callback ) {
+
+ // vars
+ var model = this;
+
+
+ // add action
+ acf.add_filter( this.tag(name), function( $field ){
+
+ // focus
+ model.set('$field', $field);
+
+
+ // callback
+ model[ callback ].apply(model, arguments);
+
+ });
+
+ },
+
+ _add_event: function( name, callback ) {
+
+ // vars
+ var model = this;
+ var event = name.substr(0,name.indexOf(' '));
+ var selector = name.substr(name.indexOf(' ')+1);
+ var context = this.selector();
+
+
+ // add event
+ $(document).on(event, context + ' ' + selector, function( e ){
+
+ // append $el to event object
+ e.$el = $(this);
+ e.$field = e.$el.closest('.acf-field-object');
+
+
+ // focus
+ model.set('$field', e.$field);
+
+
+ // callback
+ model[ callback ].apply(model, [e]);
+
+ });
+
+ },
+
+ _set_$field: function(){
+
+ // vars
+ this.o = this.$field.data();
+
+
+ // els
+ this.$settings = this.$field.find('> .settings > table > tbody');
+
+
+ // focus
+ this.focus();
+
+ },
+
+ focus: function(){
+
+ // do nothing
+
+ },
+
+ setting: function( name ) {
+
+ return this.$settings.find('> .acf-field-setting-' + name);
+
+ }
+
+ });
+
+
+ /*
+ * field
+ *
+ * This model fires actions and filters for registered fields
+ *
+ * @type function
+ * @date 21/02/2014
+ * @since 3.5.1
+ *
+ * @param n/a
+ * @return n/a
+ */
+
+ var actionManager = new acf.Model({
+
+ actions: {
+ 'open_field_object': 'onOpenFieldObject',
+ 'close_field_object': 'onCloseFieldObject',
+ 'add_field_object': 'onAddFieldObject',
+ 'duplicate_field_object': 'onDuplicateFieldObject',
+ 'delete_field_object': 'onDeleteFieldObject',
+ 'change_field_object_type': 'onChangeFieldObjectType',
+ 'change_field_object_label': 'onChangeFieldObjectLabel',
+ 'change_field_object_name': 'onChangeFieldObjectName',
+ 'change_field_object_parent': 'onChangeFieldObjectParent',
+ 'sortstop_field_object': 'onChangeFieldObjectParent'
+ },
+
+ onOpenFieldObject: function( field ){
+ acf.doAction('open_field', field.$el);
+ acf.doAction('open_field/type=' + field.get('type'), field.$el);
+
+ acf.doAction('render_field_settings', field.$el);
+ acf.doAction('render_field_settings/type=' + field.get('type'), field.$el);
+ },
+
+ onCloseFieldObject: function( field ){
+ acf.doAction('close_field', field.$el);
+ acf.doAction('close_field/type=' + field.get('type'), field.$el);
+ },
+
+ onAddFieldObject: function( field ){
+ acf.doAction('add_field', field.$el);
+ acf.doAction('add_field/type=' + field.get('type'), field.$el);
+ },
+
+ onDuplicateFieldObject: function( field ){
+ acf.doAction('duplicate_field', field.$el);
+ acf.doAction('duplicate_field/type=' + field.get('type'), field.$el);
+ },
+
+ onDeleteFieldObject: function( field ){
+ acf.doAction('delete_field', field.$el);
+ acf.doAction('delete_field/type=' + field.get('type'), field.$el);
+ },
+
+ onChangeFieldObjectType: function( field ){
+ acf.doAction('change_field_type', field.$el);
+ acf.doAction('change_field_type/type=' + field.get('type'), field.$el);
+
+ acf.doAction('render_field_settings', field.$el);
+ acf.doAction('render_field_settings/type=' + field.get('type'), field.$el);
+ },
+
+ onChangeFieldObjectLabel: function( field ){
+ acf.doAction('change_field_label', field.$el);
+ acf.doAction('change_field_label/type=' + field.get('type'), field.$el);
+ },
+
+ onChangeFieldObjectName: function( field ){
+ acf.doAction('change_field_name', field.$el);
+ acf.doAction('change_field_name/type=' + field.get('type'), field.$el);
+ },
+
+ onChangeFieldObjectParent: function( field ){
+ acf.doAction('update_field_parent', field.$el);
+ }
+ });
+
})(jQuery);
\ No newline at end of file
diff --git a/assets/build/js/acf-input.js b/assets/build/js/acf-input.js
index 992c08c..37aec7b 100644
--- a/assets/build/js/acf-input.js
+++ b/assets/build/js/acf-input.js
@@ -1,9253 +1,10883 @@
-(function ($, undefined) {
- // vars
- var storage = [];
- /**
- * acf.Field
- *
- * description
- *
- * @date 23/3/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.Field = acf.Model.extend({
- // field type
- type: '',
- // class used to avoid nested event triggers
- eventScope: '.acf-field',
- // initialize events on 'ready'
- wait: 'ready',
-
- /**
- * setup
- *
- * Called during the constructor function to setup this field ready for initialization
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param jQuery $field The field element.
- * @return void
- */
- setup: function ($field) {
- // set $el
- this.$el = $field; // inherit $field data
-
- this.inherit($field); // inherit controll data
-
- this.inherit(this.$control());
- },
-
- /**
- * val
- *
- * Sets or returns the field's value
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param mixed val Optional. The value to set
- * @return mixed
- */
- val: function (val) {
- // Set.
- if (val !== undefined) {
- return this.setValue(val); // Get.
- } else {
- return this.prop('disabled') ? null : this.getValue();
- }
- },
-
- /**
- * getValue
- *
- * returns the field's value
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param void
- * @return mixed
- */
- getValue: function () {
- return this.$input().val();
- },
-
- /**
- * setValue
- *
- * sets the field's value and returns true if changed
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param mixed val
- * @return boolean. True if changed.
- */
- setValue: function (val) {
- return acf.val(this.$input(), val);
- },
-
- /**
- * __
- *
- * i18n helper to be removed
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- __: function (string) {
- return acf._e(this.type, string);
- },
-
- /**
- * $control
- *
- * returns the control jQuery element used for inheriting data. Uses this.control setting.
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param void
- * @return jQuery
- */
- $control: function () {
- return false;
- },
-
- /**
- * $input
- *
- * returns the input jQuery element used for saving values. Uses this.input setting.
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param void
- * @return jQuery
- */
- $input: function () {
- return this.$('[name]:first');
- },
-
- /**
- * $inputWrap
- *
- * description
- *
- * @date 12/5/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- $inputWrap: function () {
- return this.$('.acf-input:first');
- },
-
- /**
- * $inputWrap
- *
- * description
- *
- * @date 12/5/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- $labelWrap: function () {
- return this.$('.acf-label:first');
- },
-
- /**
- * getInputName
- *
- * Returns the field's input name
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param void
- * @return string
- */
- getInputName: function () {
- return this.$input().attr('name') || '';
- },
-
- /**
- * parent
- *
- * returns the field's parent field or false on failure.
- *
- * @date 8/5/18
- * @since 5.6.9
- *
- * @param void
- * @return object|false
- */
- parent: function () {
- // vars
- var parents = this.parents(); // return
-
- return parents.length ? parents[0] : false;
- },
-
- /**
- * parents
- *
- * description
- *
- * @date 9/7/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- parents: function () {
- // vars
- var $parents = this.$el.parents('.acf-field'); // convert
-
- var parents = acf.getFields($parents); // return
-
- return parents;
- },
- show: function (lockKey, context) {
- // show field and store result
- var changed = acf.show(this.$el, lockKey); // do action if visibility has changed
-
- if (changed) {
- this.prop('hidden', false);
- acf.doAction('show_field', this, context);
- } // return
-
-
- return changed;
- },
- hide: function (lockKey, context) {
- // hide field and store result
- var changed = acf.hide(this.$el, lockKey); // do action if visibility has changed
-
- if (changed) {
- this.prop('hidden', true);
- acf.doAction('hide_field', this, context);
- } // return
-
-
- return changed;
- },
- enable: function (lockKey, context) {
- // enable field and store result
- var changed = acf.enable(this.$el, lockKey); // do action if disabled has changed
-
- if (changed) {
- this.prop('disabled', false);
- acf.doAction('enable_field', this, context);
- } // return
-
-
- return changed;
- },
- disable: function (lockKey, context) {
- // disabled field and store result
- var changed = acf.disable(this.$el, lockKey); // do action if disabled has changed
-
- if (changed) {
- this.prop('disabled', true);
- acf.doAction('disable_field', this, context);
- } // return
-
-
- return changed;
- },
- showEnable: function (lockKey, context) {
- // enable
- this.enable.apply(this, arguments); // show and return true if changed
-
- return this.show.apply(this, arguments);
- },
- hideDisable: function (lockKey, context) {
- // disable
- this.disable.apply(this, arguments); // hide and return true if changed
-
- return this.hide.apply(this, arguments);
- },
- showNotice: function (props) {
- // ensure object
- if (typeof props !== 'object') {
- props = {
- text: props
- };
- } // remove old notice
-
-
- if (this.notice) {
- this.notice.remove();
- } // create new notice
-
-
- props.target = this.$inputWrap();
- this.notice = acf.newNotice(props);
- },
- removeNotice: function (timeout) {
- if (this.notice) {
- this.notice.away(timeout || 0);
- this.notice = false;
- }
- },
- showError: function (message) {
- // add class
- this.$el.addClass('acf-error'); // add message
-
- if (message !== undefined) {
- this.showNotice({
- text: message,
- type: 'error',
- dismiss: false
- });
- } // action
-
-
- acf.doAction('invalid_field', this); // add event
-
- this.$el.one('focus change', 'input, select, textarea', $.proxy(this.removeError, this));
- },
- removeError: function () {
- // remove class
- this.$el.removeClass('acf-error'); // remove notice
-
- this.removeNotice(250); // action
-
- acf.doAction('valid_field', this);
- },
- trigger: function (name, args, bubbles) {
- // allow some events to bubble
- if (name == 'invalidField') {
- bubbles = true;
- } // return
-
-
- return acf.Model.prototype.trigger.apply(this, [name, args, bubbles]);
- }
- });
- /**
- * newField
- *
- * description
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.newField = function ($field) {
- // vars
- var type = $field.data('type');
- var mid = modelId(type);
- var model = acf.models[mid] || acf.Field; // instantiate
-
- var field = new model($field); // actions
-
- acf.doAction('new_field', field); // return
-
- return field;
- };
- /**
- * mid
- *
- * Calculates the model ID for a field type
- *
- * @date 15/12/17
- * @since 5.6.5
- *
- * @param string type
- * @return string
- */
-
-
- var modelId = function (type) {
- return acf.strPascalCase(type || '') + 'Field';
- };
- /**
- * registerFieldType
- *
- * description
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.registerFieldType = function (model) {
- // vars
- var proto = model.prototype;
- var type = proto.type;
- var mid = modelId(type); // store model
-
- acf.models[mid] = model; // store reference
-
- storage.push(type);
- };
- /**
- * acf.getFieldType
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.getFieldType = function (type) {
- var mid = modelId(type);
- return acf.models[mid] || false;
- };
- /**
- * acf.getFieldTypes
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.getFieldTypes = function (args) {
- // defaults
- args = acf.parseArgs(args, {
- category: '' // hasValue: true
-
- }); // clonse available types
-
- var types = []; // loop
-
- storage.map(function (type) {
- // vars
- var model = acf.getFieldType(type);
- var proto = model.prototype; // check operator
-
- if (args.category && proto.category !== args.category) {
- return;
- } // append
-
-
- types.push(model);
- }); // return
-
- return types;
- };
+(function($, undefined){
+
+ // vars
+ var storage = [];
+
+ /**
+ * acf.Field
+ *
+ * description
+ *
+ * @date 23/3/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.Field = acf.Model.extend({
+
+ // field type
+ type: '',
+
+ // class used to avoid nested event triggers
+ eventScope: '.acf-field',
+
+ // initialize events on 'ready'
+ wait: 'ready',
+
+ /**
+ * setup
+ *
+ * Called during the constructor function to setup this field ready for initialization
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param jQuery $field The field element.
+ * @return void
+ */
+
+ setup: function( $field ){
+
+ // set $el
+ this.$el = $field;
+
+ // inherit $field data
+ this.inherit( $field );
+
+ // inherit controll data
+ this.inherit( this.$control() );
+ },
+
+ /**
+ * val
+ *
+ * Sets or returns the field's value
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param mixed val Optional. The value to set
+ * @return mixed
+ */
+
+ val: function( val ){
+
+ // Set.
+ if( val !== undefined ) {
+ return this.setValue( val );
+
+ // Get.
+ } else {
+ return this.prop('disabled') ? null : this.getValue();
+ }
+ },
+
+ /**
+ * getValue
+ *
+ * returns the field's value
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return mixed
+ */
+
+ getValue: function(){
+ return this.$input().val();
+ },
+
+ /**
+ * setValue
+ *
+ * sets the field's value and returns true if changed
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param mixed val
+ * @return boolean. True if changed.
+ */
+
+ setValue: function( val ){
+ return acf.val( this.$input(), val );
+ },
+
+ /**
+ * __
+ *
+ * i18n helper to be removed
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ __: function( string ){
+ return acf._e( this.type, string );
+ },
+
+ /**
+ * $control
+ *
+ * returns the control jQuery element used for inheriting data. Uses this.control setting.
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return jQuery
+ */
+
+ $control: function(){
+ return false;
+ },
+
+ /**
+ * $input
+ *
+ * returns the input jQuery element used for saving values. Uses this.input setting.
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return jQuery
+ */
+
+ $input: function(){
+ return this.$('[name]:first');
+ },
+
+ /**
+ * $inputWrap
+ *
+ * description
+ *
+ * @date 12/5/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ $inputWrap: function(){
+ return this.$('.acf-input:first');
+ },
+
+ /**
+ * $inputWrap
+ *
+ * description
+ *
+ * @date 12/5/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ $labelWrap: function(){
+ return this.$('.acf-label:first');
+ },
+
+ /**
+ * getInputName
+ *
+ * Returns the field's input name
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return string
+ */
+
+ getInputName: function(){
+ return this.$input().attr('name') || '';
+ },
+
+ /**
+ * parent
+ *
+ * returns the field's parent field or false on failure.
+ *
+ * @date 8/5/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return object|false
+ */
+
+ parent: function() {
+
+ // vars
+ var parents = this.parents();
+
+ // return
+ return parents.length ? parents[0] : false;
+ },
+
+ /**
+ * parents
+ *
+ * description
+ *
+ * @date 9/7/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ parents: function(){
+
+ // vars
+ var $parents = this.$el.parents('.acf-field');
+
+ // convert
+ var parents = acf.getFields( $parents );
+
+ // return
+ return parents;
+ },
+
+ show: function( lockKey, context ){
+
+ // show field and store result
+ var changed = acf.show( this.$el, lockKey );
+
+ // do action if visibility has changed
+ if( changed ) {
+ this.prop('hidden', false);
+ acf.doAction('show_field', this, context);
+ }
+
+ // return
+ return changed;
+ },
+
+ hide: function( lockKey, context ){
+
+ // hide field and store result
+ var changed = acf.hide( this.$el, lockKey );
+
+ // do action if visibility has changed
+ if( changed ) {
+ this.prop('hidden', true);
+ acf.doAction('hide_field', this, context);
+ }
+
+ // return
+ return changed;
+ },
+
+ enable: function( lockKey, context ){
+
+ // enable field and store result
+ var changed = acf.enable( this.$el, lockKey );
+
+ // do action if disabled has changed
+ if( changed ) {
+ this.prop('disabled', false);
+ acf.doAction('enable_field', this, context);
+ }
+
+ // return
+ return changed;
+ },
+
+ disable: function( lockKey, context ){
+
+ // disabled field and store result
+ var changed = acf.disable( this.$el, lockKey );
+
+ // do action if disabled has changed
+ if( changed ) {
+ this.prop('disabled', true);
+ acf.doAction('disable_field', this, context);
+ }
+
+ // return
+ return changed;
+ },
+
+ showEnable: function( lockKey, context ){
+
+ // enable
+ this.enable.apply(this, arguments);
+
+ // show and return true if changed
+ return this.show.apply(this, arguments);
+ },
+
+ hideDisable: function( lockKey, context ){
+
+ // disable
+ this.disable.apply(this, arguments);
+
+ // hide and return true if changed
+ return this.hide.apply(this, arguments);
+ },
+
+ showNotice: function( props ){
+
+ // ensure object
+ if( typeof props !== 'object' ) {
+ props = { text: props };
+ }
+
+ // remove old notice
+ if( this.notice ) {
+ this.notice.remove();
+ }
+
+ // create new notice
+ props.target = this.$inputWrap();
+ this.notice = acf.newNotice( props );
+ },
+
+ removeNotice: function( timeout ){
+ if( this.notice ) {
+ this.notice.away( timeout || 0 );
+ this.notice = false;
+ }
+ },
+
+ showError: function( message ){
+
+ // add class
+ this.$el.addClass('acf-error');
+
+ // add message
+ if( message !== undefined ) {
+ this.showNotice({
+ text: message,
+ type: 'error',
+ dismiss: false
+ });
+ }
+
+ // action
+ acf.doAction('invalid_field', this);
+
+ // add event
+ this.$el.one('focus change', 'input, select, textarea', $.proxy( this.removeError, this ));
+ },
+
+ removeError: function(){
+
+ // remove class
+ this.$el.removeClass('acf-error');
+
+ // remove notice
+ this.removeNotice( 250 );
+
+ // action
+ acf.doAction('valid_field', this);
+ },
+
+ trigger: function( name, args, bubbles ){
+
+ // allow some events to bubble
+ if( name == 'invalidField' ) {
+ bubbles = true;
+ }
+
+ // return
+ return acf.Model.prototype.trigger.apply(this, [name, args, bubbles]);
+ },
+ });
+
+ /**
+ * newField
+ *
+ * description
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.newField = function( $field ){
+
+ // vars
+ var type = $field.data('type');
+ var mid = modelId( type );
+ var model = acf.models[ mid ] || acf.Field;
+
+ // instantiate
+ var field = new model( $field );
+
+ // actions
+ acf.doAction('new_field', field);
+
+ // return
+ return field;
+ };
+
+ /**
+ * mid
+ *
+ * Calculates the model ID for a field type
+ *
+ * @date 15/12/17
+ * @since 5.6.5
+ *
+ * @param string type
+ * @return string
+ */
+
+ var modelId = function( type ) {
+ return acf.strPascalCase( type || '' ) + 'Field';
+ };
+
+ /**
+ * registerFieldType
+ *
+ * description
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.registerFieldType = function( model ){
+
+ // vars
+ var proto = model.prototype;
+ var type = proto.type;
+ var mid = modelId( type );
+
+ // store model
+ acf.models[ mid ] = model;
+
+ // store reference
+ storage.push( type );
+ };
+
+ /**
+ * acf.getFieldType
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.getFieldType = function( type ){
+ var mid = modelId( type );
+ return acf.models[ mid ] || false;
+ }
+
+ /**
+ * acf.getFieldTypes
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.getFieldTypes = function( args ){
+
+ // defaults
+ args = acf.parseArgs(args, {
+ category: '',
+ // hasValue: true
+ });
+
+ // clonse available types
+ var types = [];
+
+ // loop
+ storage.map(function( type ){
+
+ // vars
+ var model = acf.getFieldType(type);
+ var proto = model.prototype;
+
+ // check operator
+ if( args.category && proto.category !== args.category ) {
+ return;
+ }
+
+ // append
+ types.push( model );
+ });
+
+ // return
+ return types;
+ };
+
})(jQuery);
-
-(function ($, undefined) {
- /**
- * findFields
- *
- * Returns a jQuery selection object of acf fields.
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param object $args {
- * Optional. Arguments to find fields.
- *
- * @type string key The field's key (data-attribute).
- * @type string name The field's name (data-attribute).
- * @type string type The field's type (data-attribute).
- * @type string is jQuery selector to compare against.
- * @type jQuery parent jQuery element to search within.
- * @type jQuery sibling jQuery element to search alongside.
- * @type limit int The number of fields to find.
- * @type suppressFilters bool Whether to allow filters to add/remove results. Default behaviour will ignore clone fields.
- * }
- * @return jQuery
- */
- acf.findFields = function (args) {
- // vars
- var selector = '.acf-field';
- var $fields = false; // args
-
- args = acf.parseArgs(args, {
- key: '',
- name: '',
- type: '',
- is: '',
- parent: false,
- sibling: false,
- limit: false,
- visible: false,
- suppressFilters: false
- }); // filter args
-
- if (!args.suppressFilters) {
- args = acf.applyFilters('find_fields_args', args);
- } // key
-
-
- if (args.key) {
- selector += '[data-key="' + args.key + '"]';
- } // type
-
-
- if (args.type) {
- selector += '[data-type="' + args.type + '"]';
- } // name
-
-
- if (args.name) {
- selector += '[data-name="' + args.name + '"]';
- } // is
-
-
- if (args.is) {
- selector += args.is;
- } // visibility
-
-
- if (args.visible) {
- selector += ':visible';
- } // query
-
-
- if (args.parent) {
- $fields = args.parent.find(selector);
- } else if (args.sibling) {
- $fields = args.sibling.siblings(selector);
- } else {
- $fields = $(selector);
- } // filter
-
-
- if (!args.suppressFilters) {
- $fields = $fields.not('.acf-clone .acf-field');
- $fields = acf.applyFilters('find_fields', $fields);
- } // limit
-
-
- if (args.limit) {
- $fields = $fields.slice(0, args.limit);
- } // return
-
-
- return $fields;
- };
- /**
- * findField
- *
- * Finds a specific field with jQuery
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param string key The field's key.
- * @param jQuery $parent jQuery element to search within.
- * @return jQuery
- */
-
-
- acf.findField = function (key, $parent) {
- return acf.findFields({
- key: key,
- limit: 1,
- parent: $parent,
- suppressFilters: true
- });
- };
- /**
- * getField
- *
- * Returns a field instance
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param jQuery|string $field jQuery element or field key.
- * @return object
- */
-
-
- acf.getField = function ($field) {
- // allow jQuery
- if ($field instanceof jQuery) {// find fields
- } else {
- $field = acf.findField($field);
- } // instantiate
-
-
- var field = $field.data('acf');
-
- if (!field) {
- field = acf.newField($field);
- } // return
-
-
- return field;
- };
- /**
- * getFields
- *
- * Returns multiple field instances
- *
- * @date 14/12/17
- * @since 5.6.5
- *
- * @param jQuery|object $fields jQuery elements or query args.
- * @return array
- */
-
-
- acf.getFields = function ($fields) {
- // allow jQuery
- if ($fields instanceof jQuery) {// find fields
- } else {
- $fields = acf.findFields($fields);
- } // loop
-
-
- var fields = [];
- $fields.each(function () {
- var field = acf.getField($(this));
- fields.push(field);
- }); // return
-
- return fields;
- };
- /**
- * findClosestField
- *
- * Returns the closest jQuery field element
- *
- * @date 9/4/18
- * @since 5.6.9
- *
- * @param jQuery $el
- * @return jQuery
- */
-
-
- acf.findClosestField = function ($el) {
- return $el.closest('.acf-field');
- };
- /**
- * getClosestField
- *
- * Returns the closest field instance
- *
- * @date 22/1/18
- * @since 5.6.5
- *
- * @param jQuery $el
- * @return object
- */
-
-
- acf.getClosestField = function ($el) {
- var $field = acf.findClosestField($el);
- return this.getField($field);
- };
- /**
- * addGlobalFieldAction
- *
- * Sets up callback logic for global field actions
- *
- * @date 15/6/18
- * @since 5.6.9
- *
- * @param string action
- * @return void
- */
-
-
- var addGlobalFieldAction = function (action) {
- // vars
- var globalAction = action;
- var pluralAction = action + '_fields'; // ready_fields
-
- var singleAction = action + '_field'; // ready_field
- // global action
-
- var globalCallback = function ($el
- /*, arg1, arg2, etc*/
- ) {
- //console.log( action, arguments );
- // get args [$el, ...]
- var args = acf.arrayArgs(arguments);
- var extraArgs = args.slice(1); // find fields
-
- var fields = acf.getFields({
- parent: $el
- }); // check
-
- if (fields.length) {
- // pluralAction
- var pluralArgs = [pluralAction, fields].concat(extraArgs);
- acf.doAction.apply(null, pluralArgs);
- }
- }; // plural action
-
-
- var pluralCallback = function (fields
- /*, arg1, arg2, etc*/
- ) {
- //console.log( pluralAction, arguments );
- // get args [fields, ...]
- var args = acf.arrayArgs(arguments);
- var extraArgs = args.slice(1); // loop
-
- fields.map(function (field, i) {
- //setTimeout(function(){
- // singleAction
- var singleArgs = [singleAction, field].concat(extraArgs);
- acf.doAction.apply(null, singleArgs); //}, i * 100);
- });
- }; // add actions
-
-
- acf.addAction(globalAction, globalCallback);
- acf.addAction(pluralAction, pluralCallback); // also add single action
-
- addSingleFieldAction(action);
- };
- /**
- * addSingleFieldAction
- *
- * Sets up callback logic for single field actions
- *
- * @date 15/6/18
- * @since 5.6.9
- *
- * @param string action
- * @return void
- */
-
-
- var addSingleFieldAction = function (action) {
- // vars
- var singleAction = action + '_field'; // ready_field
-
- var singleEvent = action + 'Field'; // readyField
- // single action
-
- var singleCallback = function (field
- /*, arg1, arg2, etc*/
- ) {
- //console.log( singleAction, arguments );
- // get args [field, ...]
- var args = acf.arrayArgs(arguments);
- var extraArgs = args.slice(1); // action variations (ready_field/type=image)
-
- var variations = ['type', 'name', 'key'];
- variations.map(function (variation) {
- // vars
- var prefix = '/' + variation + '=' + field.get(variation); // singleAction
-
- args = [singleAction + prefix, field].concat(extraArgs);
- acf.doAction.apply(null, args);
- }); // event
-
- if (singleFieldEvents.indexOf(action) > -1) {
- field.trigger(singleEvent, extraArgs);
- }
- }; // add actions
-
-
- acf.addAction(singleAction, singleCallback);
- }; // vars
-
-
- var globalFieldActions = ['prepare', 'ready', 'load', 'append', 'remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload'];
- var singleFieldActions = ['valid', 'invalid', 'enable', 'disable', 'new', 'duplicate'];
- var singleFieldEvents = ['remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload', 'valid', 'invalid', 'enable', 'disable', 'duplicate']; // add
-
- globalFieldActions.map(addGlobalFieldAction);
- singleFieldActions.map(addSingleFieldAction);
- /**
- * fieldsEventManager
- *
- * Manages field actions and events
- *
- * @date 15/12/17
- * @since 5.6.5
- *
- * @param void
- * @param void
- */
-
- var fieldsEventManager = new acf.Model({
- id: 'fieldsEventManager',
- events: {
- 'click .acf-field a[href="#"]': 'onClick',
- 'change .acf-field': 'onChange'
- },
- onClick: function (e) {
- // prevent default of any link with an href of #
- e.preventDefault();
- },
- onChange: function () {
- // preview hack allows post to save with no title or content
- $('#_acf_changed').val(1);
- }
- });
- var duplicateFieldsManager = new acf.Model({
- id: 'duplicateFieldsManager',
- actions: {
- 'duplicate': 'onDuplicate',
- 'duplicate_fields': 'onDuplicateFields'
- },
- onDuplicate: function ($el, $el2) {
- var fields = acf.getFields({
- parent: $el
- });
-
- if (fields.length) {
- var $fields = acf.findFields({
- parent: $el2
- });
- acf.doAction('duplicate_fields', fields, $fields);
- }
- },
- onDuplicateFields: function (fields, duplicates) {
- fields.map(function (field, i) {
- acf.doAction('duplicate_field', field, $(duplicates[i]));
- });
- }
- });
+(function($, undefined){
+
+ /**
+ * findFields
+ *
+ * Returns a jQuery selection object of acf fields.
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param object $args {
+ * Optional. Arguments to find fields.
+ *
+ * @type string key The field's key (data-attribute).
+ * @type string name The field's name (data-attribute).
+ * @type string type The field's type (data-attribute).
+ * @type string is jQuery selector to compare against.
+ * @type jQuery parent jQuery element to search within.
+ * @type jQuery sibling jQuery element to search alongside.
+ * @type limit int The number of fields to find.
+ * @type suppressFilters bool Whether to allow filters to add/remove results. Default behaviour will ignore clone fields.
+ * }
+ * @return jQuery
+ */
+
+ acf.findFields = function( args ){
+
+ // vars
+ var selector = '.acf-field';
+ var $fields = false;
+
+ // args
+ args = acf.parseArgs(args, {
+ key: '',
+ name: '',
+ type: '',
+ is: '',
+ parent: false,
+ sibling: false,
+ limit: false,
+ visible: false,
+ suppressFilters: false,
+ });
+
+ // filter args
+ if( !args.suppressFilters ) {
+ args = acf.applyFilters('find_fields_args', args);
+ }
+
+ // key
+ if( args.key ) {
+ selector += '[data-key="' + args.key + '"]';
+ }
+
+ // type
+ if( args.type ) {
+ selector += '[data-type="' + args.type + '"]';
+ }
+
+ // name
+ if( args.name ) {
+ selector += '[data-name="' + args.name + '"]';
+ }
+
+ // is
+ if( args.is ) {
+ selector += args.is;
+ }
+
+ // visibility
+ if( args.visible ) {
+ selector += ':visible';
+ }
+
+ // query
+ if( args.parent ) {
+ $fields = args.parent.find( selector );
+ } else if( args.sibling ) {
+ $fields = args.sibling.siblings( selector );
+ } else {
+ $fields = $( selector );
+ }
+
+ // filter
+ if( !args.suppressFilters ) {
+ $fields = $fields.not('.acf-clone .acf-field');
+ $fields = acf.applyFilters('find_fields', $fields);
+ }
+
+ // limit
+ if( args.limit ) {
+ $fields = $fields.slice( 0, args.limit );
+ }
+
+ // return
+ return $fields;
+
+ };
+
+ /**
+ * findField
+ *
+ * Finds a specific field with jQuery
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param string key The field's key.
+ * @param jQuery $parent jQuery element to search within.
+ * @return jQuery
+ */
+
+ acf.findField = function( key, $parent ){
+ return acf.findFields({
+ key: key,
+ limit: 1,
+ parent: $parent,
+ suppressFilters: true
+ });
+ };
+
+ /**
+ * getField
+ *
+ * Returns a field instance
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param jQuery|string $field jQuery element or field key.
+ * @return object
+ */
+
+ acf.getField = function( $field ){
+
+ // allow jQuery
+ if( $field instanceof jQuery ) {
+
+ // find fields
+ } else {
+ $field = acf.findField( $field );
+ }
+
+ // instantiate
+ var field = $field.data('acf');
+ if( !field ) {
+ field = acf.newField( $field );
+ }
+
+ // return
+ return field;
+ };
+
+ /**
+ * getFields
+ *
+ * Returns multiple field instances
+ *
+ * @date 14/12/17
+ * @since 5.6.5
+ *
+ * @param jQuery|object $fields jQuery elements or query args.
+ * @return array
+ */
+
+ acf.getFields = function( $fields ){
+
+ // allow jQuery
+ if( $fields instanceof jQuery ) {
+
+ // find fields
+ } else {
+ $fields = acf.findFields( $fields );
+ }
+
+ // loop
+ var fields = [];
+ $fields.each(function(){
+ var field = acf.getField( $(this) );
+ fields.push( field );
+ });
+
+ // return
+ return fields;
+ };
+
+ /**
+ * findClosestField
+ *
+ * Returns the closest jQuery field element
+ *
+ * @date 9/4/18
+ * @since 5.6.9
+ *
+ * @param jQuery $el
+ * @return jQuery
+ */
+
+ acf.findClosestField = function( $el ){
+ return $el.closest('.acf-field');
+ };
+
+ /**
+ * getClosestField
+ *
+ * Returns the closest field instance
+ *
+ * @date 22/1/18
+ * @since 5.6.5
+ *
+ * @param jQuery $el
+ * @return object
+ */
+
+ acf.getClosestField = function( $el ){
+ var $field = acf.findClosestField( $el );
+ return this.getField( $field );
+ };
+
+ /**
+ * addGlobalFieldAction
+ *
+ * Sets up callback logic for global field actions
+ *
+ * @date 15/6/18
+ * @since 5.6.9
+ *
+ * @param string action
+ * @return void
+ */
+
+ var addGlobalFieldAction = function( action ){
+
+ // vars
+ var globalAction = action;
+ var pluralAction = action + '_fields'; // ready_fields
+ var singleAction = action + '_field'; // ready_field
+
+ // global action
+ var globalCallback = function( $el /*, arg1, arg2, etc*/ ){
+ //console.log( action, arguments );
+
+ // get args [$el, ...]
+ var args = acf.arrayArgs( arguments );
+ var extraArgs = args.slice(1);
+
+ // find fields
+ var fields = acf.getFields({ parent: $el });
+
+ // check
+ if( fields.length ) {
+
+ // pluralAction
+ var pluralArgs = [ pluralAction, fields ].concat( extraArgs );
+ acf.doAction.apply(null, pluralArgs);
+ }
+ };
+
+ // plural action
+ var pluralCallback = function( fields /*, arg1, arg2, etc*/ ){
+ //console.log( pluralAction, arguments );
+
+ // get args [fields, ...]
+ var args = acf.arrayArgs( arguments );
+ var extraArgs = args.slice(1);
+
+ // loop
+ fields.map(function( field, i ){
+ //setTimeout(function(){
+ // singleAction
+ var singleArgs = [ singleAction, field ].concat( extraArgs );
+ acf.doAction.apply(null, singleArgs);
+ //}, i * 100);
+ });
+ };
+
+ // add actions
+ acf.addAction(globalAction, globalCallback);
+ acf.addAction(pluralAction, pluralCallback);
+
+ // also add single action
+ addSingleFieldAction( action );
+ }
+
+ /**
+ * addSingleFieldAction
+ *
+ * Sets up callback logic for single field actions
+ *
+ * @date 15/6/18
+ * @since 5.6.9
+ *
+ * @param string action
+ * @return void
+ */
+
+ var addSingleFieldAction = function( action ){
+
+ // vars
+ var singleAction = action + '_field'; // ready_field
+ var singleEvent = action + 'Field'; // readyField
+
+ // single action
+ var singleCallback = function( field /*, arg1, arg2, etc*/ ){
+ //console.log( singleAction, arguments );
+
+ // get args [field, ...]
+ var args = acf.arrayArgs( arguments );
+ var extraArgs = args.slice(1);
+
+ // action variations (ready_field/type=image)
+ var variations = ['type', 'name', 'key'];
+ variations.map(function( variation ){
+
+ // vars
+ var prefix = '/' + variation + '=' + field.get(variation);
+
+ // singleAction
+ args = [ singleAction + prefix , field ].concat( extraArgs );
+ acf.doAction.apply(null, args);
+ });
+
+ // event
+ if( singleFieldEvents.indexOf(action) > -1 ) {
+ field.trigger(singleEvent, extraArgs);
+ }
+ };
+
+ // add actions
+ acf.addAction(singleAction, singleCallback);
+ }
+
+ // vars
+ var globalFieldActions = [ 'prepare', 'ready', 'load', 'append', 'remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload' ];
+ var singleFieldActions = [ 'valid', 'invalid', 'enable', 'disable', 'new', 'duplicate' ];
+ var singleFieldEvents = [ 'remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload', 'valid', 'invalid', 'enable', 'disable', 'duplicate' ];
+
+ // add
+ globalFieldActions.map( addGlobalFieldAction );
+ singleFieldActions.map( addSingleFieldAction );
+
+ /**
+ * fieldsEventManager
+ *
+ * Manages field actions and events
+ *
+ * @date 15/12/17
+ * @since 5.6.5
+ *
+ * @param void
+ * @param void
+ */
+
+ var fieldsEventManager = new acf.Model({
+ id: 'fieldsEventManager',
+ events: {
+ 'click .acf-field a[href="#"]': 'onClick',
+ 'change .acf-field': 'onChange'
+ },
+ onClick: function( e ){
+
+ // prevent default of any link with an href of #
+ e.preventDefault();
+ },
+ onChange: function(){
+
+ // preview hack allows post to save with no title or content
+ $('#_acf_changed').val(1);
+ }
+ });
+
+ var duplicateFieldsManager = new acf.Model({
+ id: 'duplicateFieldsManager',
+ actions: {
+ 'duplicate': 'onDuplicate',
+ 'duplicate_fields': 'onDuplicateFields',
+ },
+ onDuplicate: function( $el, $el2 ){
+ var fields = acf.getFields({ parent: $el });
+ if( fields.length ) {
+ var $fields = acf.findFields({ parent: $el2 });
+ acf.doAction( 'duplicate_fields', fields, $fields );
+ }
+ },
+ onDuplicateFields: function( fields, duplicates ){
+ fields.map(function( field, i ){
+ acf.doAction( 'duplicate_field', field, $(duplicates[i]) );
+ });
+ }
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- var i = 0;
- var Field = acf.Field.extend({
- type: 'accordion',
- wait: '',
- $control: function () {
- return this.$('.acf-fields:first');
- },
- initialize: function () {
- // Bail early if this is a duplicate of an existing initialized accordion.
- if (this.$el.hasClass('acf-accordion')) {
- return;
- } // bail early if is cell
+(function($, undefined){
+
+ var i = 0;
+
+ var Field = acf.Field.extend({
+
+ type: 'accordion',
+
+ wait: '',
+
+ $control: function(){
+ return this.$('.acf-fields:first');
+ },
+
+ initialize: function(){
+
+ // Bail early if this is a duplicate of an existing initialized accordion.
+ if( this.$el.hasClass('acf-accordion') ) {
+ return;
+ }
+
+ // bail early if is cell
+ if( this.$el.is('td') ) return;
+
+ // enpoint
+ if( this.get('endpoint') ) {
+ return this.remove();
+ }
+
+ // vars
+ var $field = this.$el;
+ var $label = this.$labelWrap()
+ var $input = this.$inputWrap();
+ var $wrap = this.$control();
+ var $instructions = $input.children('.description');
+
+ // force description into label
+ if( $instructions.length ) {
+ $label.append( $instructions );
+ }
+
+ // table
+ if( this.$el.is('tr') ) {
+
+ // vars
+ var $table = this.$el.closest('table');
+ var $newLabel = $('
');
+ var $newInput = $('
');
+ var $newTable = $('');
+ var $newWrap = $(' ');
+
+ // dom
+ $newLabel.append( $label.html() );
+ $newTable.append( $newWrap );
+ $newInput.append( $newTable );
+ $input.append( $newLabel );
+ $input.append( $newInput );
+
+ // modify
+ $label.remove();
+ $wrap.remove();
+ $input.attr('colspan', 2);
+
+ // update vars
+ $label = $newLabel;
+ $input = $newInput;
+ $wrap = $newWrap;
+ }
+
+ // add classes
+ $field.addClass('acf-accordion');
+ $label.addClass('acf-accordion-title');
+ $input.addClass('acf-accordion-content');
+
+ // index
+ i++;
+
+ // multi-expand
+ if( this.get('multi_expand') ) {
+ $field.attr('multi-expand', 1);
+ }
+
+ // open
+ var order = acf.getPreference('this.accordions') || [];
+ if( order[i-1] !== undefined ) {
+ this.set('open', order[i-1]);
+ }
+
+ if( this.get('open') ) {
+ $field.addClass('-open');
+ $input.css('display', 'block'); // needed for accordion to close smoothly
+ }
+
+ // add icon
+ $label.prepend( accordionManager.iconHtml({ open: this.get('open') }) );
+
+ // classes
+ // - remove 'inside' which is a #poststuff WP class
+ var $parent = $field.parent();
+ $wrap.addClass( $parent.hasClass('-left') ? '-left' : '' );
+ $wrap.addClass( $parent.hasClass('-clear') ? '-clear' : '' );
+
+ // append
+ $wrap.append( $field.nextUntil('.acf-field-accordion', '.acf-field') );
+
+ // clean up
+ $wrap.removeAttr('data-open data-multi_expand data-endpoint');
+ },
+
+ });
+
+ acf.registerFieldType( Field );
- if (this.$el.is('td')) return; // enpoint
+ /**
+ * accordionManager
+ *
+ * Events manager for the acf accordion
+ *
+ * @date 14/2/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return void
+ */
+
+ var accordionManager = new acf.Model({
+
+ actions: {
+ 'unload': 'onUnload'
+ },
+
+ events: {
+ 'click .acf-accordion-title': 'onClick',
+ 'invalidField .acf-accordion': 'onInvalidField'
+ },
+
+ isOpen: function( $el ) {
+ return $el.hasClass('-open');
+ },
+
+ toggle: function( $el ){
+ if( this.isOpen($el) ) {
+ this.close( $el );
+ } else {
+ this.open( $el );
+ }
+ },
+
+ iconHtml: function( props ){
+
+ // Use SVG inside Gutenberg editor.
+ if( acf.isGutenberg() ) {
+ if( props.open ) {
+ return ' ';
+ } else {
+ return ' ';
+ }
+ } else {
+ if( props.open ) {
+ return ' ';
+ } else {
+ return ' ';
+ }
+ }
+ },
+
+ open: function( $el ){
+ var duration = acf.isGutenberg() ? 0 : 300;
+
+ // open
+ $el.find('.acf-accordion-content:first').slideDown( duration ).css('display', 'block');
+ $el.find('.acf-accordion-icon:first').replaceWith( this.iconHtml({ open: true }) );
+ $el.addClass('-open');
+
+ // action
+ acf.doAction('show', $el);
+
+ // close siblings
+ if( !$el.attr('multi-expand') ) {
+ $el.siblings('.acf-accordion.-open').each(function(){
+ accordionManager.close( $(this) );
+ });
+ }
+ },
+
+ close: function( $el ){
+ var duration = acf.isGutenberg() ? 0 : 300;
+
+ // close
+ $el.find('.acf-accordion-content:first').slideUp( duration );
+ $el.find('.acf-accordion-icon:first').replaceWith( this.iconHtml({ open: false }) );
+ $el.removeClass('-open');
+
+ // action
+ acf.doAction('hide', $el);
+ },
+
+ onClick: function( e, $el ){
+
+ // prevent Defailt
+ e.preventDefault();
+
+ // open close
+ this.toggle( $el.parent() );
+
+ },
+
+ onInvalidField: function( e, $el ){
+
+ // bail early if already focused
+ if( this.busy ) {
+ return;
+ }
+
+ // disable functionality for 1sec (allow next validation to work)
+ this.busy = true;
+ this.setTimeout(function(){
+ this.busy = false;
+ }, 1000);
+
+ // open accordion
+ this.open( $el );
+ },
+
+ onUnload: function( e ){
+
+ // vars
+ var order = [];
+
+ // loop
+ $('.acf-accordion').each(function(){
+ var open = $(this).hasClass('-open') ? 1 : 0;
+ order.push(open);
+ });
+
+ // set
+ if( order.length ) {
+ acf.setPreference('this.accordions', order);
+ }
+ }
+ });
- if (this.get('endpoint')) {
- return this.remove();
- } // vars
-
-
- var $field = this.$el;
- var $label = this.$labelWrap();
- var $input = this.$inputWrap();
- var $wrap = this.$control();
- var $instructions = $input.children('.description'); // force description into label
-
- if ($instructions.length) {
- $label.append($instructions);
- } // table
-
-
- if (this.$el.is('tr')) {
- // vars
- var $table = this.$el.closest('table');
- var $newLabel = $('
');
- var $newInput = $('
');
- var $newTable = $('');
- var $newWrap = $(' '); // dom
-
- $newLabel.append($label.html());
- $newTable.append($newWrap);
- $newInput.append($newTable);
- $input.append($newLabel);
- $input.append($newInput); // modify
-
- $label.remove();
- $wrap.remove();
- $input.attr('colspan', 2); // update vars
-
- $label = $newLabel;
- $input = $newInput;
- $wrap = $newWrap;
- } // add classes
-
-
- $field.addClass('acf-accordion');
- $label.addClass('acf-accordion-title');
- $input.addClass('acf-accordion-content'); // index
-
- i++; // multi-expand
-
- if (this.get('multi_expand')) {
- $field.attr('multi-expand', 1);
- } // open
-
-
- var order = acf.getPreference('this.accordions') || [];
-
- if (order[i - 1] !== undefined) {
- this.set('open', order[i - 1]);
- }
-
- if (this.get('open')) {
- $field.addClass('-open');
- $input.css('display', 'block'); // needed for accordion to close smoothly
- } // add icon
-
-
- $label.prepend(accordionManager.iconHtml({
- open: this.get('open')
- })); // classes
- // - remove 'inside' which is a #poststuff WP class
-
- var $parent = $field.parent();
- $wrap.addClass($parent.hasClass('-left') ? '-left' : '');
- $wrap.addClass($parent.hasClass('-clear') ? '-clear' : ''); // append
-
- $wrap.append($field.nextUntil('.acf-field-accordion', '.acf-field')); // clean up
-
- $wrap.removeAttr('data-open data-multi_expand data-endpoint');
- }
- });
- acf.registerFieldType(Field);
- /**
- * accordionManager
- *
- * Events manager for the acf accordion
- *
- * @date 14/2/18
- * @since 5.6.9
- *
- * @param void
- * @return void
- */
-
- var accordionManager = new acf.Model({
- actions: {
- 'unload': 'onUnload'
- },
- events: {
- 'click .acf-accordion-title': 'onClick',
- 'invalidField .acf-accordion': 'onInvalidField'
- },
- isOpen: function ($el) {
- return $el.hasClass('-open');
- },
- toggle: function ($el) {
- if (this.isOpen($el)) {
- this.close($el);
- } else {
- this.open($el);
- }
- },
- iconHtml: function (props) {
- // Use SVG inside Gutenberg editor.
- if (acf.isGutenberg()) {
- if (props.open) {
- return ' ';
- } else {
- return ' ';
- }
- } else {
- if (props.open) {
- return ' ';
- } else {
- return ' ';
- }
- }
- },
- open: function ($el) {
- var duration = acf.isGutenberg() ? 0 : 300; // open
-
- $el.find('.acf-accordion-content:first').slideDown(duration).css('display', 'block');
- $el.find('.acf-accordion-icon:first').replaceWith(this.iconHtml({
- open: true
- }));
- $el.addClass('-open'); // action
-
- acf.doAction('show', $el); // close siblings
-
- if (!$el.attr('multi-expand')) {
- $el.siblings('.acf-accordion.-open').each(function () {
- accordionManager.close($(this));
- });
- }
- },
- close: function ($el) {
- var duration = acf.isGutenberg() ? 0 : 300; // close
-
- $el.find('.acf-accordion-content:first').slideUp(duration);
- $el.find('.acf-accordion-icon:first').replaceWith(this.iconHtml({
- open: false
- }));
- $el.removeClass('-open'); // action
-
- acf.doAction('hide', $el);
- },
- onClick: function (e, $el) {
- // prevent Defailt
- e.preventDefault(); // open close
-
- this.toggle($el.parent());
- },
- onInvalidField: function (e, $el) {
- // bail early if already focused
- if (this.busy) {
- return;
- } // disable functionality for 1sec (allow next validation to work)
-
-
- this.busy = true;
- this.setTimeout(function () {
- this.busy = false;
- }, 1000); // open accordion
-
- this.open($el);
- },
- onUnload: function (e) {
- // vars
- var order = []; // loop
-
- $('.acf-accordion').each(function () {
- var open = $(this).hasClass('-open') ? 1 : 0;
- order.push(open);
- }); // set
-
- if (order.length) {
- acf.setPreference('this.accordions', order);
- }
- }
- });
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'button_group',
+
+ events: {
+ 'click input[type="radio"]': 'onClick'
+ },
+
+ $control: function(){
+ return this.$('.acf-button-group');
+ },
+
+ $input: function(){
+ return this.$('input:checked');
+ },
+
+ setValue: function( val ){
+ this.$('input[value="' + val + '"]').prop('checked', true).trigger('change');
+ },
+
+ onClick: function( e, $el ){
+
+ // vars
+ var $label = $el.parent('label');
+ var selected = $label.hasClass('selected');
+
+ // remove previous selected
+ this.$('.selected').removeClass('selected');
+
+ // add active class
+ $label.addClass('selected');
+
+ // allow null
+ if( this.get('allow_null') && selected ) {
+ $label.removeClass('selected');
+ $el.prop('checked', false).trigger('change');
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'button_group',
- events: {
- 'click input[type="radio"]': 'onClick'
- },
- $control: function () {
- return this.$('.acf-button-group');
- },
- $input: function () {
- return this.$('input:checked');
- },
- setValue: function (val) {
- this.$('input[value="' + val + '"]').prop('checked', true).trigger('change');
- },
- onClick: function (e, $el) {
- // vars
- var $label = $el.parent('label');
- var selected = $label.hasClass('selected'); // remove previous selected
-
- this.$('.selected').removeClass('selected'); // add active class
-
- $label.addClass('selected'); // allow null
-
- if (this.get('allow_null') && selected) {
- $label.removeClass('selected');
- $el.prop('checked', false).trigger('change');
- }
- }
- });
- acf.registerFieldType(Field);
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'checkbox',
- events: {
- 'change input': 'onChange',
- 'click .acf-add-checkbox': 'onClickAdd',
- 'click .acf-checkbox-toggle': 'onClickToggle',
- 'click .acf-checkbox-custom': 'onClickCustom'
- },
- $control: function () {
- return this.$('.acf-checkbox-list');
- },
- $toggle: function () {
- return this.$('.acf-checkbox-toggle');
- },
- $input: function () {
- return this.$('input[type="hidden"]');
- },
- $inputs: function () {
- return this.$('input[type="checkbox"]').not('.acf-checkbox-toggle');
- },
- getValue: function () {
- var val = [];
- this.$(':checked').each(function () {
- val.push($(this).val());
- });
- return val.length ? val : false;
- },
- onChange: function (e, $el) {
- // Vars.
- var checked = $el.prop('checked');
- var $label = $el.parent('label');
- var $toggle = this.$toggle(); // Add or remove "selected" class.
-
- if (checked) {
- $label.addClass('selected');
- } else {
- $label.removeClass('selected');
- } // Update toggle state if all inputs are checked.
-
-
- if ($toggle.length) {
- var $inputs = this.$inputs(); // all checked
-
- if ($inputs.not(':checked').length == 0) {
- $toggle.prop('checked', true);
- } else {
- $toggle.prop('checked', false);
- }
- }
- },
- onClickAdd: function (e, $el) {
- var html = ' ';
- $el.parent('li').before(html);
- },
- onClickToggle: function (e, $el) {
- // Vars.
- var checked = $el.prop('checked');
- var $inputs = this.$('input[type="checkbox"]');
- var $labels = this.$('label'); // Update "checked" state.
-
- $inputs.prop('checked', checked); // Add or remove "selected" class.
-
- if (checked) {
- $labels.addClass('selected');
- } else {
- $labels.removeClass('selected');
- }
- },
- onClickCustom: function (e, $el) {
- var checked = $el.prop('checked');
- var $text = $el.next('input[type="text"]'); // checked
-
- if (checked) {
- $text.prop('disabled', false); // not checked
- } else {
- $text.prop('disabled', true); // remove
-
- if ($text.val() == '') {
- $el.parent('li').remove();
- }
- }
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'checkbox',
+
+ events: {
+ 'change input': 'onChange',
+ 'click .acf-add-checkbox': 'onClickAdd',
+ 'click .acf-checkbox-toggle': 'onClickToggle',
+ 'click .acf-checkbox-custom': 'onClickCustom'
+ },
+
+ $control: function(){
+ return this.$('.acf-checkbox-list');
+ },
+
+ $toggle: function(){
+ return this.$('.acf-checkbox-toggle');
+ },
+
+ $input: function(){
+ return this.$('input[type="hidden"]');
+ },
+
+ $inputs: function(){
+ return this.$('input[type="checkbox"]').not('.acf-checkbox-toggle');
+ },
+
+ getValue: function(){
+ var val = [];
+ this.$(':checked').each(function(){
+ val.push( $(this).val() );
+ });
+ return val.length ? val : false;
+ },
+
+ onChange: function( e, $el ){
+
+ // Vars.
+ var checked = $el.prop('checked');
+ var $label = $el.parent('label');
+ var $toggle = this.$toggle();
+
+ // Add or remove "selected" class.
+ if( checked ) {
+ $label.addClass('selected');
+ } else {
+ $label.removeClass('selected');
+ }
+
+ // Update toggle state if all inputs are checked.
+ if( $toggle.length ) {
+ var $inputs = this.$inputs();
+
+ // all checked
+ if( $inputs.not(':checked').length == 0 ) {
+ $toggle.prop('checked', true);
+ } else {
+ $toggle.prop('checked', false);
+ }
+ }
+ },
+
+ onClickAdd: function( e, $el ){
+ var html = ' ';
+ $el.parent('li').before( html );
+ },
+
+ onClickToggle: function( e, $el ){
+
+ // Vars.
+ var checked = $el.prop('checked');
+ var $inputs = this.$('input[type="checkbox"]');
+ var $labels = this.$('label');
+
+ // Update "checked" state.
+ $inputs.prop('checked', checked);
+
+ // Add or remove "selected" class.
+ if( checked ) {
+ $labels.addClass('selected');
+ } else {
+ $labels.removeClass('selected');
+ }
+ },
+
+ onClickCustom: function( e, $el ){
+ var checked = $el.prop('checked');
+ var $text = $el.next('input[type="text"]');
+
+ // checked
+ if( checked ) {
+ $text.prop('disabled', false);
+
+ // not checked
+ } else {
+ $text.prop('disabled', true);
+
+ // remove
+ if( $text.val() == '' ) {
+ $el.parent('li').remove();
+ }
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'color_picker',
+
+ wait: 'load',
+
+ events: {
+ 'duplicateField': 'onDuplicate'
+ },
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'color_picker',
- wait: 'load',
- events: {
- 'duplicateField': 'onDuplicate'
- },
- $control: function () {
- return this.$('.acf-color-picker');
- },
- $input: function () {
- return this.$('input[type="hidden"]');
- },
- $inputText: function () {
- return this.$('input[type="text"]');
- },
- setValue: function (val) {
- // update input (with change)
- acf.val(this.$input(), val); // update iris
+ $control: function(){
+ return this.$('.acf-color-picker');
+ },
+
+ $input: function(){
+ return this.$('input[type="hidden"]');
+ },
+
+ $inputText: function(){
+ return this.$('input[type="text"]');
+ },
+
+ setValue: function( val ){
+
+ // update input (with change)
+ acf.val( this.$input(), val );
+
+ // update iris
+ this.$inputText().iris('color', val);
+ },
+
+ initialize: function(){
+
+ // vars
+ var $input = this.$input();
+ var $inputText = this.$inputText();
+
+ // event
+ var onChange = function( e ){
+
+ // timeout is required to ensure the $input val is correct
+ setTimeout(function(){
+ acf.val( $input, $inputText.val() );
+ }, 1);
+ }
+
+ // args
+ var args = {
+ defaultColor: false,
+ palettes: true,
+ hide: true,
+ change: onChange,
+ clear: onChange
+ };
+
+ // filter
+ var args = acf.applyFilters('color_picker_args', args, this);
+
+ // initialize
+ $inputText.wpColorPicker( args );
+ },
- this.$inputText().iris('color', val);
- },
- initialize: function () {
- // vars
- var $input = this.$input();
- var $inputText = this.$inputText(); // event
-
- var onChange = function (e) {
- // timeout is required to ensure the $input val is correct
- setTimeout(function () {
- acf.val($input, $inputText.val());
- }, 1);
- }; // args
-
-
- var args = {
- defaultColor: false,
- palettes: true,
- hide: true,
- change: onChange,
- clear: onChange
- }; // filter
-
- var args = acf.applyFilters('color_picker_args', args, this); // initialize
-
- $inputText.wpColorPicker(args);
- },
- onDuplicate: function (e, $el, $duplicate) {
- // The wpColorPicker library does not provide a destroy method.
- // Manually reset DOM by replacing elements back to their original state.
- $colorPicker = $duplicate.find('.wp-picker-container');
- $inputText = $duplicate.find('input[type="text"]');
- $colorPicker.replaceWith($inputText);
- }
- });
- acf.registerFieldType(Field);
+ onDuplicate: function( e, $el, $duplicate ){
+
+ // The wpColorPicker library does not provide a destroy method.
+ // Manually reset DOM by replacing elements back to their original state.
+ $colorPicker = $duplicate.find('.wp-picker-container');
+ $inputText = $duplicate.find('input[type="text"]');
+ $colorPicker.replaceWith( $inputText );
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'date_picker',
- events: {
- 'blur input[type="text"]': 'onBlur',
- 'duplicateField': 'onDuplicate'
- },
- $control: function () {
- return this.$('.acf-date-picker');
- },
- $input: function () {
- return this.$('input[type="hidden"]');
- },
- $inputText: function () {
- return this.$('input[type="text"]');
- },
- initialize: function () {
- // save_format: compatibility with ACF < 5.0.0
- if (this.has('save_format')) {
- return this.initializeCompatibility();
- } // vars
-
-
- var $input = this.$input();
- var $inputText = this.$inputText(); // args
-
- var args = {
- dateFormat: this.get('date_format'),
- altField: $input,
- altFormat: 'yymmdd',
- changeYear: true,
- yearRange: "-100:+100",
- changeMonth: true,
- showButtonPanel: true,
- firstDay: this.get('first_day')
- }; // filter
-
- args = acf.applyFilters('date_picker_args', args, this); // add date picker
-
- acf.newDatePicker($inputText, args); // action
-
- acf.doAction('date_picker_init', $inputText, args, this);
- },
- initializeCompatibility: function () {
- // vars
- var $input = this.$input();
- var $inputText = this.$inputText(); // get and set value from alt field
-
- $inputText.val($input.val()); // args
-
- var args = {
- dateFormat: this.get('date_format'),
- altField: $input,
- altFormat: this.get('save_format'),
- changeYear: true,
- yearRange: "-100:+100",
- changeMonth: true,
- showButtonPanel: true,
- firstDay: this.get('first_day')
- }; // filter for 3rd party customization
-
- args = acf.applyFilters('date_picker_args', args, this); // backup
-
- var dateFormat = args.dateFormat; // change args.dateFormat
-
- args.dateFormat = this.get('save_format'); // add date picker
-
- acf.newDatePicker($inputText, args); // now change the format back to how it should be.
-
- $inputText.datepicker('option', 'dateFormat', dateFormat); // action for 3rd party customization
-
- acf.doAction('date_picker_init', $inputText, args, this);
- },
- onBlur: function () {
- if (!this.$inputText().val()) {
- acf.val(this.$input(), '');
- }
- },
- onDuplicate: function (e, $el, $duplicate) {
- $duplicate.find('input[type="text"]').removeClass('hasDatepicker').removeAttr('id');
- }
- });
- acf.registerFieldType(Field); // manager
-
- var datePickerManager = new acf.Model({
- priority: 5,
- wait: 'ready',
- initialize: function () {
- // vars
- var locale = acf.get('locale');
- var rtl = acf.get('rtl');
- var l10n = acf.get('datePickerL10n'); // bail ealry if no l10n
-
- if (!l10n) {
- return false;
- } // bail ealry if no datepicker library
-
-
- if (typeof $.datepicker === 'undefined') {
- return false;
- } // rtl
-
-
- l10n.isRTL = rtl; // append
-
- $.datepicker.regional[locale] = l10n;
- $.datepicker.setDefaults(l10n);
- }
- }); // add
-
- acf.newDatePicker = function ($input, args) {
- // bail ealry if no datepicker library
- if (typeof $.datepicker === 'undefined') {
- return false;
- } // defaults
-
-
- args = args || {}; // initialize
-
- $input.datepicker(args); // wrap the datepicker (only if it hasn't already been wrapped)
-
- if ($('body > #ui-datepicker-div').exists()) {
- $('body > #ui-datepicker-div').wrap('
');
- }
- };
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'date_picker',
+
+ events: {
+ 'blur input[type="text"]': 'onBlur',
+ 'duplicateField': 'onDuplicate'
+ },
+
+ $control: function(){
+ return this.$('.acf-date-picker');
+ },
+
+ $input: function(){
+ return this.$('input[type="hidden"]');
+ },
+
+ $inputText: function(){
+ return this.$('input[type="text"]');
+ },
+
+ initialize: function(){
+
+ // save_format: compatibility with ACF < 5.0.0
+ if( this.has('save_format') ) {
+ return this.initializeCompatibility();
+ }
+
+ // vars
+ var $input = this.$input();
+ var $inputText = this.$inputText();
+
+ // args
+ var args = {
+ dateFormat: this.get('date_format'),
+ altField: $input,
+ altFormat: 'yymmdd',
+ changeYear: true,
+ yearRange: "-100:+100",
+ changeMonth: true,
+ showButtonPanel: true,
+ firstDay: this.get('first_day')
+ };
+
+ // filter
+ args = acf.applyFilters('date_picker_args', args, this);
+
+ // add date picker
+ acf.newDatePicker( $inputText, args );
+
+ // action
+ acf.doAction('date_picker_init', $inputText, args, this);
+
+ },
+
+ initializeCompatibility: function(){
+
+ // vars
+ var $input = this.$input();
+ var $inputText = this.$inputText();
+
+ // get and set value from alt field
+ $inputText.val( $input.val() );
+
+ // args
+ var args = {
+ dateFormat: this.get('date_format'),
+ altField: $input,
+ altFormat: this.get('save_format'),
+ changeYear: true,
+ yearRange: "-100:+100",
+ changeMonth: true,
+ showButtonPanel: true,
+ firstDay: this.get('first_day')
+ };
+
+ // filter for 3rd party customization
+ args = acf.applyFilters('date_picker_args', args, this);
+
+ // backup
+ var dateFormat = args.dateFormat;
+
+ // change args.dateFormat
+ args.dateFormat = this.get('save_format');
+
+ // add date picker
+ acf.newDatePicker( $inputText, args );
+
+ // now change the format back to how it should be.
+ $inputText.datepicker( 'option', 'dateFormat', dateFormat );
+
+ // action for 3rd party customization
+ acf.doAction('date_picker_init', $inputText, args, this);
+ },
+
+ onBlur: function(){
+ if( !this.$inputText().val() ) {
+ acf.val( this.$input(), '' );
+ }
+ },
+
+ onDuplicate: function( e, $el, $duplicate ){
+ $duplicate.find('input[type="text"]').removeClass('hasDatepicker').removeAttr('id');
+ }
+ });
+
+ acf.registerFieldType( Field );
+
+
+ // manager
+ var datePickerManager = new acf.Model({
+ priority: 5,
+ wait: 'ready',
+ initialize: function(){
+
+ // vars
+ var locale = acf.get('locale');
+ var rtl = acf.get('rtl');
+ var l10n = acf.get('datePickerL10n');
+
+ // bail ealry if no l10n
+ if( !l10n ) {
+ return false;
+ }
+
+ // bail ealry if no datepicker library
+ if( typeof $.datepicker === 'undefined' ) {
+ return false;
+ }
+
+ // rtl
+ l10n.isRTL = rtl;
+
+ // append
+ $.datepicker.regional[ locale ] = l10n;
+ $.datepicker.setDefaults(l10n);
+ }
+ });
+
+ // add
+ acf.newDatePicker = function( $input, args ){
+
+ // bail ealry if no datepicker library
+ if( typeof $.datepicker === 'undefined' ) {
+ return false;
+ }
+
+ // defaults
+ args = args || {};
+
+ // initialize
+ $input.datepicker( args );
+
+ // wrap the datepicker (only if it hasn't already been wrapped)
+ if( $('body > #ui-datepicker-div').exists() ) {
+ $('body > #ui-datepicker-div').wrap('
');
+ }
+ };
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.models.DatePickerField.extend({
- type: 'date_time_picker',
- $control: function () {
- return this.$('.acf-date-time-picker');
- },
- initialize: function () {
- // vars
- var $input = this.$input();
- var $inputText = this.$inputText(); // args
-
- var args = {
- dateFormat: this.get('date_format'),
- timeFormat: this.get('time_format'),
- altField: $input,
- altFieldTimeOnly: false,
- altFormat: 'yy-mm-dd',
- altTimeFormat: 'HH:mm:ss',
- changeYear: true,
- yearRange: "-100:+100",
- changeMonth: true,
- showButtonPanel: true,
- firstDay: this.get('first_day'),
- controlType: 'select',
- oneLine: true
- }; // filter
-
- args = acf.applyFilters('date_time_picker_args', args, this); // add date time picker
-
- acf.newDateTimePicker($inputText, args); // action
-
- acf.doAction('date_time_picker_init', $inputText, args, this);
- }
- });
- acf.registerFieldType(Field); // manager
-
- var dateTimePickerManager = new acf.Model({
- priority: 5,
- wait: 'ready',
- initialize: function () {
- // vars
- var locale = acf.get('locale');
- var rtl = acf.get('rtl');
- var l10n = acf.get('dateTimePickerL10n'); // bail ealry if no l10n
-
- if (!l10n) {
- return false;
- } // bail ealry if no datepicker library
-
-
- if (typeof $.timepicker === 'undefined') {
- return false;
- } // rtl
-
-
- l10n.isRTL = rtl; // append
-
- $.timepicker.regional[locale] = l10n;
- $.timepicker.setDefaults(l10n);
- }
- }); // add
-
- acf.newDateTimePicker = function ($input, args) {
- // bail ealry if no datepicker library
- if (typeof $.timepicker === 'undefined') {
- return false;
- } // defaults
-
-
- args = args || {}; // initialize
-
- $input.datetimepicker(args); // wrap the datepicker (only if it hasn't already been wrapped)
-
- if ($('body > #ui-datepicker-div').exists()) {
- $('body > #ui-datepicker-div').wrap('
');
- }
- };
+(function($, undefined){
+
+ var Field = acf.models.DatePickerField.extend({
+
+ type: 'date_time_picker',
+
+ $control: function(){
+ return this.$('.acf-date-time-picker');
+ },
+
+ initialize: function(){
+
+ // vars
+ var $input = this.$input();
+ var $inputText = this.$inputText();
+
+ // args
+ var args = {
+ dateFormat: this.get('date_format'),
+ timeFormat: this.get('time_format'),
+ altField: $input,
+ altFieldTimeOnly: false,
+ altFormat: 'yy-mm-dd',
+ altTimeFormat: 'HH:mm:ss',
+ changeYear: true,
+ yearRange: "-100:+100",
+ changeMonth: true,
+ showButtonPanel: true,
+ firstDay: this.get('first_day'),
+ controlType: 'select',
+ oneLine: true
+ };
+
+ // filter
+ args = acf.applyFilters('date_time_picker_args', args, this);
+
+ // add date time picker
+ acf.newDateTimePicker( $inputText, args );
+
+ // action
+ acf.doAction('date_time_picker_init', $inputText, args, this);
+ }
+ });
+
+ acf.registerFieldType( Field );
+
+
+ // manager
+ var dateTimePickerManager = new acf.Model({
+ priority: 5,
+ wait: 'ready',
+ initialize: function(){
+
+ // vars
+ var locale = acf.get('locale');
+ var rtl = acf.get('rtl');
+ var l10n = acf.get('dateTimePickerL10n');
+
+ // bail ealry if no l10n
+ if( !l10n ) {
+ return false;
+ }
+
+ // bail ealry if no datepicker library
+ if( typeof $.timepicker === 'undefined' ) {
+ return false;
+ }
+
+ // rtl
+ l10n.isRTL = rtl;
+
+ // append
+ $.timepicker.regional[ locale ] = l10n;
+ $.timepicker.setDefaults(l10n);
+ }
+ });
+
+
+ // add
+ acf.newDateTimePicker = function( $input, args ){
+
+ // bail ealry if no datepicker library
+ if( typeof $.timepicker === 'undefined' ) {
+ return false;
+ }
+
+ // defaults
+ args = args || {};
+
+ // initialize
+ $input.datetimepicker( args );
+
+ // wrap the datepicker (only if it hasn't already been wrapped)
+ if( $('body > #ui-datepicker-div').exists() ) {
+ $('body > #ui-datepicker-div').wrap('
');
+ }
+ };
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'google_map',
- map: false,
- wait: 'load',
- events: {
- 'click a[data-name="clear"]': 'onClickClear',
- 'click a[data-name="locate"]': 'onClickLocate',
- 'click a[data-name="search"]': 'onClickSearch',
- 'keydown .search': 'onKeydownSearch',
- 'keyup .search': 'onKeyupSearch',
- 'focus .search': 'onFocusSearch',
- 'blur .search': 'onBlurSearch',
- 'showField': 'onShow'
- },
- $control: function () {
- return this.$('.acf-google-map');
- },
- $search: function () {
- return this.$('.search');
- },
- $canvas: function () {
- return this.$('.canvas');
- },
- setState: function (state) {
- // Remove previous state classes.
- this.$control().removeClass('-value -loading -searching'); // Determine auto state based of current value.
-
- if (state === 'default') {
- state = this.val() ? 'value' : '';
- } // Update state class.
-
-
- if (state) {
- this.$control().addClass('-' + state);
- }
- },
- getValue: function () {
- var val = this.$input().val();
-
- if (val) {
- return JSON.parse(val);
- } else {
- return false;
- }
- },
- setValue: function (val, silent) {
- // Convert input value.
- var valAttr = '';
-
- if (val) {
- valAttr = JSON.stringify(val);
- } // Update input (with change).
-
-
- acf.val(this.$input(), valAttr); // Bail early if silent update.
-
- if (silent) {
- return;
- } // Render.
-
-
- this.renderVal(val);
- /**
- * Fires immediately after the value has changed.
- *
- * @date 12/02/2014
- * @since 5.0.0
- *
- * @param object|string val The new value.
- * @param object map The Google Map isntance.
- * @param object field The field instance.
- */
-
- acf.doAction('google_map_change', val, this.map, this);
- },
- renderVal: function (val) {
- // Value.
- if (val) {
- this.setState('value');
- this.$search().val(val.address);
- this.setPosition(val.lat, val.lng); // No value.
- } else {
- this.setState('');
- this.$search().val('');
- this.map.marker.setVisible(false);
- }
- },
- newLatLng: function (lat, lng) {
- return new google.maps.LatLng(parseFloat(lat), parseFloat(lng));
- },
- setPosition: function (lat, lng) {
- // Update marker position.
- this.map.marker.setPosition({
- lat: parseFloat(lat),
- lng: parseFloat(lng)
- }); // Show marker.
-
- this.map.marker.setVisible(true); // Center map.
-
- this.center();
- },
- center: function () {
- // Find marker position.
- var position = this.map.marker.getPosition();
-
- if (position) {
- var lat = position.lat();
- var lng = position.lng(); // Or find default settings.
- } else {
- var lat = this.get('lat');
- var lng = this.get('lng');
- } // Center map.
-
-
- this.map.setCenter({
- lat: parseFloat(lat),
- lng: parseFloat(lng)
- });
- },
- initialize: function () {
- // Ensure Google API is loaded and then initialize map.
- withAPI(this.initializeMap.bind(this));
- },
- initializeMap: function () {
- // Get value ignoring conditional logic status.
- var val = this.getValue(); // Construct default args.
-
- var args = acf.parseArgs(val, {
- zoom: this.get('zoom'),
- lat: this.get('lat'),
- lng: this.get('lng')
- }); // Create Map.
-
- var mapArgs = {
- scrollwheel: false,
- zoom: parseInt(args.zoom),
- center: {
- lat: parseFloat(args.lat),
- lng: parseFloat(args.lng)
- },
- mapTypeId: google.maps.MapTypeId.ROADMAP,
- marker: {
- draggable: true,
- raiseOnDrag: true
- },
- autocomplete: {}
- };
- mapArgs = acf.applyFilters('google_map_args', mapArgs, this);
- var map = new google.maps.Map(this.$canvas()[0], mapArgs); // Create Marker.
-
- var markerArgs = acf.parseArgs(mapArgs.marker, {
- draggable: true,
- raiseOnDrag: true,
- map: map
- });
- markerArgs = acf.applyFilters('google_map_marker_args', markerArgs, this);
- var marker = new google.maps.Marker(markerArgs); // Maybe Create Autocomplete.
-
- var autocomplete = false;
-
- if (acf.isset(google, 'maps', 'places', 'Autocomplete')) {
- var autocompleteArgs = mapArgs.autocomplete || {};
- autocompleteArgs = acf.applyFilters('google_map_autocomplete_args', autocompleteArgs, this);
- autocomplete = new google.maps.places.Autocomplete(this.$search()[0], autocompleteArgs);
- autocomplete.bindTo('bounds', map);
- } // Add map events.
-
-
- this.addMapEvents(this, map, marker, autocomplete); // Append references.
-
- map.acf = this;
- map.marker = marker;
- map.autocomplete = autocomplete;
- this.map = map; // Set position.
-
- if (val) {
- this.setPosition(val.lat, val.lng);
- }
- /**
- * Fires immediately after the Google Map has been initialized.
- *
- * @date 12/02/2014
- * @since 5.0.0
- *
- * @param object map The Google Map isntance.
- * @param object marker The Google Map marker isntance.
- * @param object field The field instance.
- */
-
-
- acf.doAction('google_map_init', map, marker, this);
- },
- addMapEvents: function (field, map, marker, autocomplete) {
- // Click map.
- google.maps.event.addListener(map, 'click', function (e) {
- var lat = e.latLng.lat();
- var lng = e.latLng.lng();
- field.searchPosition(lat, lng);
- }); // Drag marker.
-
- google.maps.event.addListener(marker, 'dragend', function () {
- var lat = this.getPosition().lat();
- var lng = this.getPosition().lng();
- field.searchPosition(lat, lng);
- }); // Autocomplete search.
-
- if (autocomplete) {
- google.maps.event.addListener(autocomplete, 'place_changed', function () {
- var place = this.getPlace();
- field.searchPlace(place);
- });
- } // Detect zoom change.
-
-
- google.maps.event.addListener(map, 'zoom_changed', function () {
- var val = field.val();
-
- if (val) {
- val.zoom = map.getZoom();
- field.setValue(val, true);
- }
- });
- },
- searchPosition: function (lat, lng) {
- //console.log('searchPosition', lat, lng );
- // Start Loading.
- this.setState('loading'); // Query Geocoder.
-
- var latLng = {
- lat: lat,
- lng: lng
- };
- geocoder.geocode({
- location: latLng
- }, function (results, status) {
- //console.log('searchPosition', arguments );
- // End Loading.
- this.setState(''); // Status failure.
-
- if (status !== 'OK') {
- this.showNotice({
- text: acf.__('Location not found: %s').replace('%s', status),
- type: 'warning'
- }); // Success.
- } else {
- var val = this.parseResult(results[0]); // Override lat/lng to match user defined marker location.
- // Avoids issue where marker "snaps" to nearest result.
-
- val.lat = lat;
- val.lng = lng;
- this.val(val);
- }
- }.bind(this));
- },
- searchPlace: function (place) {
- //console.log('searchPlace', place );
- // Bail early if no place.
- if (!place) {
- return;
- } // Selecting from the autocomplete dropdown will return a rich PlaceResult object.
- // Be sure to over-write the "formatted_address" value with the one displayed to the user for best UX.
-
-
- if (place.geometry) {
- place.formatted_address = this.$search().val();
- var val = this.parseResult(place);
- this.val(val); // Searching a custom address will return an empty PlaceResult object.
- } else if (place.name) {
- this.searchAddress(place.name);
- }
- },
- searchAddress: function (address) {
- //console.log('searchAddress', address );
- // Bail early if no address.
- if (!address) {
- return;
- } // Allow "lat,lng" search.
-
-
- var latLng = address.split(',');
-
- if (latLng.length == 2) {
- var lat = parseFloat(latLng[0]);
- var lng = parseFloat(latLng[1]);
-
- if (lat && lng) {
- return this.searchPosition(lat, lng);
- }
- } // Start Loading.
-
-
- this.setState('loading'); // Query Geocoder.
-
- geocoder.geocode({
- address: address
- }, function (results, status) {
- //console.log('searchPosition', arguments );
- // End Loading.
- this.setState(''); // Status failure.
-
- if (status !== 'OK') {
- this.showNotice({
- text: acf.__('Location not found: %s').replace('%s', status),
- type: 'warning'
- }); // Success.
- } else {
- var val = this.parseResult(results[0]); // Override address data with parameter allowing custom address to be defined in search.
-
- val.address = address; // Update value.
-
- this.val(val);
- }
- }.bind(this));
- },
- searchLocation: function () {
- //console.log('searchLocation' );
- // Check HTML5 geolocation.
- if (!navigator.geolocation) {
- return alert(acf.__('Sorry, this browser does not support geolocation'));
- } // Start Loading.
-
-
- this.setState('loading'); // Query Geolocation.
-
- navigator.geolocation.getCurrentPosition( // Success.
- function (results) {
- // End Loading.
- this.setState(''); // Search position.
-
- var lat = results.coords.latitude;
- var lng = results.coords.longitude;
- this.searchPosition(lat, lng);
- }.bind(this), // Failure.
- function (error) {
- this.setState('');
- }.bind(this));
- },
-
- /**
- * parseResult
- *
- * Returns location data for the given GeocoderResult object.
- *
- * @date 15/10/19
- * @since 5.8.6
- *
- * @param object obj A GeocoderResult object.
- * @return object
- */
- parseResult: function (obj) {
- // Construct basic data.
- var result = {
- address: obj.formatted_address,
- lat: obj.geometry.location.lat(),
- lng: obj.geometry.location.lng()
- }; // Add zoom level.
-
- result.zoom = this.map.getZoom(); // Add place ID.
-
- if (obj.place_id) {
- result.place_id = obj.place_id;
- } // Add place name.
-
-
- if (obj.name) {
- result.name = obj.name;
- } // Create search map for address component data.
-
-
- var map = {
- street_number: ['street_number'],
- street_name: ['street_address', 'route'],
- city: ['locality'],
- state: ['administrative_area_level_1', 'administrative_area_level_2', 'administrative_area_level_3', 'administrative_area_level_4', 'administrative_area_level_5'],
- post_code: ['postal_code'],
- country: ['country']
- }; // Loop over map.
-
- for (var k in map) {
- var keywords = map[k]; // Loop over address components.
-
- for (var i = 0; i < obj.address_components.length; i++) {
- var component = obj.address_components[i];
- var component_type = component.types[0]; // Look for matching component type.
-
- if (keywords.indexOf(component_type) !== -1) {
- // Append to result.
- result[k] = component.long_name; // Append short version.
-
- if (component.long_name !== component.short_name) {
- result[k + '_short'] = component.short_name;
- }
- }
- }
- }
- /**
- * Filters the parsed result.
- *
- * @date 18/10/19
- * @since 5.8.6
- *
- * @param object result The parsed result value.
- * @param object obj The GeocoderResult object.
- */
-
-
- return acf.applyFilters('google_map_result', result, obj, this.map, this);
- },
- onClickClear: function () {
- this.val(false);
- },
- onClickLocate: function () {
- this.searchLocation();
- },
- onClickSearch: function () {
- this.searchAddress(this.$search().val());
- },
- onFocusSearch: function (e, $el) {
- this.setState('searching');
- },
- onBlurSearch: function (e, $el) {
- // Get saved address value.
- var val = this.val();
- var address = val ? val.address : ''; // Remove 'is-searching' if value has not changed.
-
- if ($el.val() === address) {
- this.setState('default');
- }
- },
- onKeyupSearch: function (e, $el) {
- // Clear empty value.
- if (!$el.val()) {
- this.val(false);
- }
- },
- // Prevent form from submitting.
- onKeydownSearch: function (e, $el) {
- if (e.which == 13) {
- e.preventDefault();
- $el.blur();
- }
- },
- // Center map once made visible.
- onShow: function () {
- if (this.map) {
- this.setTimeout(this.center);
- }
- }
- });
- acf.registerFieldType(Field); // Vars.
-
- var loading = false;
- var geocoder = false;
- /**
- * withAPI
- *
- * Loads the Google Maps API library and troggers callback.
- *
- * @date 28/3/19
- * @since 5.7.14
- *
- * @param function callback The callback to excecute.
- * @return void
- */
-
- function withAPI(callback) {
- // Check if geocoder exists.
- if (geocoder) {
- return callback();
- } // Check if geocoder API exists.
-
-
- if (acf.isset(window, 'google', 'maps', 'Geocoder')) {
- geocoder = new google.maps.Geocoder();
- return callback();
- } // Geocoder will need to be loaded. Hook callback to action.
-
-
- acf.addAction('google_map_api_loaded', callback); // Bail early if already loading API.
-
- if (loading) {
- return;
- } // load api
-
-
- var url = acf.get('google_map_api');
-
- if (url) {
- // Set loading status.
- loading = true; // Load API
-
- $.ajax({
- url: url,
- dataType: 'script',
- cache: true,
- success: function () {
- geocoder = new google.maps.Geocoder();
- acf.doAction('google_map_api_loaded');
- }
- });
- }
- }
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'google_map',
+
+ map: false,
+
+ wait: 'load',
+
+ events: {
+ 'click a[data-name="clear"]': 'onClickClear',
+ 'click a[data-name="locate"]': 'onClickLocate',
+ 'click a[data-name="search"]': 'onClickSearch',
+ 'keydown .search': 'onKeydownSearch',
+ 'keyup .search': 'onKeyupSearch',
+ 'focus .search': 'onFocusSearch',
+ 'blur .search': 'onBlurSearch',
+ 'showField': 'onShow',
+ },
+
+ $control: function(){
+ return this.$('.acf-google-map');
+ },
+
+ $search: function(){
+ return this.$('.search');
+ },
+
+ $canvas: function(){
+ return this.$('.canvas');
+ },
+
+ setState: function( state ){
+
+ // Remove previous state classes.
+ this.$control().removeClass( '-value -loading -searching' );
+
+ // Determine auto state based of current value.
+ if( state === 'default' ) {
+ state = this.val() ? 'value' : '';
+ }
+
+ // Update state class.
+ if( state ) {
+ this.$control().addClass( '-' + state );
+ }
+ },
+
+ getValue: function(){
+ var val = this.$input().val();
+ if( val ) {
+ return JSON.parse( val )
+ } else {
+ return false;
+ }
+ },
+
+ setValue: function( val, silent ){
+
+ // Convert input value.
+ var valAttr = '';
+ if( val ) {
+ valAttr = JSON.stringify( val );
+ }
+
+ // Update input (with change).
+ acf.val( this.$input(), valAttr );
+
+ // Bail early if silent update.
+ if( silent ) {
+ return;
+ }
+
+ // Render.
+ this.renderVal( val );
+
+ /**
+ * Fires immediately after the value has changed.
+ *
+ * @date 12/02/2014
+ * @since 5.0.0
+ *
+ * @param object|string val The new value.
+ * @param object map The Google Map isntance.
+ * @param object field The field instance.
+ */
+ acf.doAction('google_map_change', val, this.map, this);
+ },
+
+ renderVal: function( val ){
+
+ // Value.
+ if( val ) {
+ this.setState( 'value' );
+ this.$search().val( val.address );
+ this.setPosition( val.lat, val.lng );
+
+ // No value.
+ } else {
+ this.setState( '' );
+ this.$search().val( '' );
+ this.map.marker.setVisible( false );
+ }
+ },
+
+ newLatLng: function( lat, lng ){
+ return new google.maps.LatLng( parseFloat(lat), parseFloat(lng) );
+ },
+
+ setPosition: function( lat, lng ){
+
+ // Update marker position.
+ this.map.marker.setPosition({
+ lat: parseFloat(lat),
+ lng: parseFloat(lng)
+ });
+
+ // Show marker.
+ this.map.marker.setVisible( true );
+
+ // Center map.
+ this.center();
+ },
+
+ center: function(){
+
+ // Find marker position.
+ var position = this.map.marker.getPosition();
+ if( position ) {
+ var lat = position.lat();
+ var lng = position.lng();
+
+ // Or find default settings.
+ } else {
+ var lat = this.get('lat');
+ var lng = this.get('lng');
+ }
+
+ // Center map.
+ this.map.setCenter({
+ lat: parseFloat(lat),
+ lng: parseFloat(lng)
+ });
+ },
+
+ initialize: function(){
+
+ // Ensure Google API is loaded and then initialize map.
+ withAPI( this.initializeMap.bind(this) );
+ },
+
+ initializeMap: function(){
+
+ // Get value ignoring conditional logic status.
+ var val = this.getValue();
+
+ // Construct default args.
+ var args = acf.parseArgs(val, {
+ zoom: this.get('zoom'),
+ lat: this.get('lat'),
+ lng: this.get('lng')
+ });
+
+ // Create Map.
+ var mapArgs = {
+ scrollwheel: false,
+ zoom: parseInt( args.zoom ),
+ center: {
+ lat: parseFloat( args.lat ),
+ lng: parseFloat( args.lng )
+ },
+ mapTypeId: google.maps.MapTypeId.ROADMAP,
+ marker: {
+ draggable: true,
+ raiseOnDrag: true
+ },
+ autocomplete: {}
+ };
+ mapArgs = acf.applyFilters('google_map_args', mapArgs, this);
+ var map = new google.maps.Map( this.$canvas()[0], mapArgs );
+
+ // Create Marker.
+ var markerArgs = acf.parseArgs(mapArgs.marker, {
+ draggable: true,
+ raiseOnDrag: true,
+ map: map
+ });
+ markerArgs = acf.applyFilters('google_map_marker_args', markerArgs, this);
+ var marker = new google.maps.Marker( markerArgs );
+
+ // Maybe Create Autocomplete.
+ var autocomplete = false;
+ if( acf.isset(google, 'maps', 'places', 'Autocomplete') ) {
+ var autocompleteArgs = mapArgs.autocomplete || {};
+ autocompleteArgs = acf.applyFilters('google_map_autocomplete_args', autocompleteArgs, this);
+ autocomplete = new google.maps.places.Autocomplete( this.$search()[0], autocompleteArgs );
+ autocomplete.bindTo('bounds', map);
+ }
+
+ // Add map events.
+ this.addMapEvents( this, map, marker, autocomplete );
+
+ // Append references.
+ map.acf = this;
+ map.marker = marker;
+ map.autocomplete = autocomplete;
+ this.map = map;
+
+ // Set position.
+ if( val ) {
+ this.setPosition( val.lat, val.lng );
+ }
+
+ /**
+ * Fires immediately after the Google Map has been initialized.
+ *
+ * @date 12/02/2014
+ * @since 5.0.0
+ *
+ * @param object map The Google Map isntance.
+ * @param object marker The Google Map marker isntance.
+ * @param object field The field instance.
+ */
+ acf.doAction('google_map_init', map, marker, this);
+ },
+
+ addMapEvents: function( field, map, marker, autocomplete ){
+
+ // Click map.
+ google.maps.event.addListener( map, 'click', function( e ) {
+ var lat = e.latLng.lat();
+ var lng = e.latLng.lng();
+ field.searchPosition( lat, lng );
+ });
+
+ // Drag marker.
+ google.maps.event.addListener( marker, 'dragend', function(){
+ var lat = this.getPosition().lat();
+ var lng = this.getPosition().lng();
+ field.searchPosition( lat, lng );
+ });
+
+ // Autocomplete search.
+ if( autocomplete ) {
+ google.maps.event.addListener(autocomplete, 'place_changed', function() {
+ var place = this.getPlace();
+ field.searchPlace( place );
+ });
+ }
+
+ // Detect zoom change.
+ google.maps.event.addListener( map, 'zoom_changed', function(){
+ var val = field.val();
+ if( val ) {
+ val.zoom = map.getZoom();
+ field.setValue( val, true );
+ }
+ });
+ },
+
+ searchPosition: function( lat, lng ){
+ //console.log('searchPosition', lat, lng );
+
+ // Start Loading.
+ this.setState( 'loading' );
+
+ // Query Geocoder.
+ var latLng = { lat: lat, lng: lng };
+ geocoder.geocode({ location: latLng }, function( results, status ){
+ //console.log('searchPosition', arguments );
+
+ // End Loading.
+ this.setState( '' );
+
+ // Status failure.
+ if( status !== 'OK' ) {
+ this.showNotice({
+ text: acf.__('Location not found: %s').replace('%s', status),
+ type: 'warning'
+ });
+
+ // Success.
+ } else {
+ var val = this.parseResult( results[0] );
+
+ // Override lat/lng to match user defined marker location.
+ // Avoids issue where marker "snaps" to nearest result.
+ val.lat = lat;
+ val.lng = lng;
+ this.val( val );
+ }
+
+ }.bind( this ));
+ },
+
+ searchPlace: function( place ){
+ //console.log('searchPlace', place );
+
+ // Bail early if no place.
+ if( !place ) {
+ return;
+ }
+
+ // Selecting from the autocomplete dropdown will return a rich PlaceResult object.
+ // Be sure to over-write the "formatted_address" value with the one displayed to the user for best UX.
+ if( place.geometry ) {
+ place.formatted_address = this.$search().val();
+ var val = this.parseResult( place );
+ this.val( val );
+
+ // Searching a custom address will return an empty PlaceResult object.
+ } else if( place.name ) {
+ this.searchAddress( place.name );
+ }
+ },
+
+ searchAddress: function( address ){
+ //console.log('searchAddress', address );
+
+ // Bail early if no address.
+ if( !address ) {
+ return;
+ }
+
+ // Allow "lat,lng" search.
+ var latLng = address.split(',');
+ if( latLng.length == 2 ) {
+ var lat = parseFloat(latLng[0]);
+ var lng = parseFloat(latLng[1]);
+ if( lat && lng ) {
+ return this.searchPosition( lat, lng );
+ }
+ }
+
+ // Start Loading.
+ this.setState( 'loading' );
+
+ // Query Geocoder.
+ geocoder.geocode({ address: address }, function( results, status ){
+ //console.log('searchPosition', arguments );
+
+ // End Loading.
+ this.setState( '' );
+
+ // Status failure.
+ if( status !== 'OK' ) {
+ this.showNotice({
+ text: acf.__('Location not found: %s').replace('%s', status),
+ type: 'warning'
+ });
+
+ // Success.
+ } else {
+ var val = this.parseResult( results[0] );
+
+ // Override address data with parameter allowing custom address to be defined in search.
+ val.address = address;
+
+ // Update value.
+ this.val( val );
+ }
+
+ }.bind( this ));
+ },
+
+ searchLocation: function(){
+ //console.log('searchLocation' );
+
+ // Check HTML5 geolocation.
+ if( !navigator.geolocation ) {
+ return alert( acf.__('Sorry, this browser does not support geolocation') );
+ }
+
+ // Start Loading.
+ this.setState( 'loading' );
+
+ // Query Geolocation.
+ navigator.geolocation.getCurrentPosition(
+
+ // Success.
+ function( results ){
+
+ // End Loading.
+ this.setState( '' );
+
+ // Search position.
+ var lat = results.coords.latitude;
+ var lng = results.coords.longitude;
+ this.searchPosition( lat, lng );
+
+ }.bind(this),
+
+ // Failure.
+ function( error ){
+ this.setState( '' );
+ }.bind(this)
+ );
+ },
+
+ /**
+ * parseResult
+ *
+ * Returns location data for the given GeocoderResult object.
+ *
+ * @date 15/10/19
+ * @since 5.8.6
+ *
+ * @param object obj A GeocoderResult object.
+ * @return object
+ */
+ parseResult: function( obj ) {
+
+ // Construct basic data.
+ var result = {
+ address: obj.formatted_address,
+ lat: obj.geometry.location.lat(),
+ lng: obj.geometry.location.lng(),
+ };
+
+ // Add zoom level.
+ result.zoom = this.map.getZoom();
+
+ // Add place ID.
+ if( obj.place_id ) {
+ result.place_id = obj.place_id;
+ }
+
+ // Add place name.
+ if( obj.name ) {
+ result.name = obj.name;
+ }
+
+ // Create search map for address component data.
+ var map = {
+ street_number: [ 'street_number' ],
+ street_name: [ 'street_address', 'route' ],
+ city: [ 'locality' ],
+ state: [
+ 'administrative_area_level_1',
+ 'administrative_area_level_2',
+ 'administrative_area_level_3',
+ 'administrative_area_level_4',
+ 'administrative_area_level_5'
+ ],
+ post_code: [ 'postal_code' ],
+ country: [ 'country' ]
+ };
+
+ // Loop over map.
+ for( var k in map ) {
+ var keywords = map[ k ];
+
+ // Loop over address components.
+ for( var i = 0; i < obj.address_components.length; i++ ) {
+ var component = obj.address_components[ i ];
+ var component_type = component.types[0];
+
+ // Look for matching component type.
+ if( keywords.indexOf(component_type) !== -1 ) {
+
+ // Append to result.
+ result[ k ] = component.long_name;
+
+ // Append short version.
+ if( component.long_name !== component.short_name ) {
+ result[ k + '_short' ] = component.short_name;
+ }
+ }
+ }
+ }
+
+ /**
+ * Filters the parsed result.
+ *
+ * @date 18/10/19
+ * @since 5.8.6
+ *
+ * @param object result The parsed result value.
+ * @param object obj The GeocoderResult object.
+ */
+ return acf.applyFilters('google_map_result', result, obj, this.map, this);
+ },
+
+ onClickClear: function(){
+ this.val( false );
+ },
+
+ onClickLocate: function(){
+ this.searchLocation();
+ },
+
+ onClickSearch: function(){
+ this.searchAddress( this.$search().val() );
+ },
+
+ onFocusSearch: function( e, $el ){
+ this.setState( 'searching' );
+ },
+
+ onBlurSearch: function( e, $el ){
+
+ // Get saved address value.
+ var val = this.val();
+ var address = val ? val.address : '';
+
+ // Remove 'is-searching' if value has not changed.
+ if( $el.val() === address ) {
+ this.setState( 'default' );
+ }
+ },
+
+ onKeyupSearch: function( e, $el ){
+
+ // Clear empty value.
+ if( !$el.val() ) {
+ this.val( false );
+ }
+ },
+
+ // Prevent form from submitting.
+ onKeydownSearch: function( e, $el ){
+ if( e.which == 13 ) {
+ e.preventDefault();
+ $el.blur();
+ }
+ },
+
+ // Center map once made visible.
+ onShow: function(){
+ if( this.map ) {
+ this.setTimeout( this.center );
+ }
+ },
+ });
+
+ acf.registerFieldType( Field );
+
+ // Vars.
+ var loading = false;
+ var geocoder = false;
+
+ /**
+ * withAPI
+ *
+ * Loads the Google Maps API library and troggers callback.
+ *
+ * @date 28/3/19
+ * @since 5.7.14
+ *
+ * @param function callback The callback to excecute.
+ * @return void
+ */
+
+ function withAPI( callback ) {
+
+ // Check if geocoder exists.
+ if( geocoder ) {
+ return callback();
+ }
+
+ // Check if geocoder API exists.
+ if( acf.isset(window, 'google', 'maps', 'Geocoder') ) {
+ geocoder = new google.maps.Geocoder();
+ return callback();
+ }
+
+ // Geocoder will need to be loaded. Hook callback to action.
+ acf.addAction( 'google_map_api_loaded', callback );
+
+ // Bail early if already loading API.
+ if( loading ) {
+ return;
+ }
+
+ // load api
+ var url = acf.get('google_map_api');
+ if( url ) {
+
+ // Set loading status.
+ loading = true;
+
+ // Load API
+ $.ajax({
+ url: url,
+ dataType: 'script',
+ cache: true,
+ success: function(){
+ geocoder = new google.maps.Geocoder();
+ acf.doAction('google_map_api_loaded');
+ }
+ });
+ }
+ }
+
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'image',
+
+ $control: function(){
+ return this.$('.acf-image-uploader');
+ },
+
+ $input: function(){
+ return this.$('input[type="hidden"]');
+ },
+
+ events: {
+ 'click a[data-name="add"]': 'onClickAdd',
+ 'click a[data-name="edit"]': 'onClickEdit',
+ 'click a[data-name="remove"]': 'onClickRemove',
+ 'change input[type="file"]': 'onChange'
+ },
+
+ initialize: function(){
+
+ // add attribute to form
+ if( this.get('uploader') === 'basic' ) {
+ this.$el.closest('form').attr('enctype', 'multipart/form-data');
+ }
+ },
+
+ validateAttachment: function( attachment ){
+
+ // Use WP attachment attributes when available.
+ if( attachment && attachment.attributes ) {
+ attachment = attachment.attributes;
+ }
+
+ // Apply defaults.
+ attachment = acf.parseArgs(attachment, {
+ id: 0,
+ url: '',
+ alt: '',
+ title: '',
+ caption: '',
+ description: '',
+ width: 0,
+ height: 0
+ });
+
+ // Override with "preview size".
+ var size = acf.isget( attachment, 'sizes', this.get('preview_size') );
+ if( size ) {
+ attachment.url = size.url;
+ attachment.width = size.width;
+ attachment.height = size.height;
+ }
+
+ // Return.
+ return attachment;
+ },
+
+ render: function( attachment ){
+ attachment = this.validateAttachment( attachment );
+
+ // Update DOM.
+ this.$('img').attr({
+ src: attachment.url,
+ alt: attachment.alt
+ });
+ if( attachment.id ) {
+ this.val( attachment.id );
+ this.$control().addClass('has-value');
+ } else {
+ this.val( '' );
+ this.$control().removeClass('has-value');
+ }
+ },
+
+ // create a new repeater row and render value
+ append: function( attachment, parent ){
+
+ // create function to find next available field within parent
+ var getNext = function( field, parent ){
+
+ // find existing file fields within parent
+ var fields = acf.getFields({
+ key: field.get('key'),
+ parent: parent.$el
+ });
+
+ // find the first field with no value
+ for( var i = 0; i < fields.length; i++ ) {
+ if( !fields[i].val() ) {
+ return fields[i];
+ }
+ }
+
+ // return
+ return false;
+ }
+
+ // find existing file fields within parent
+ var field = getNext( this, parent );
+
+ // add new row if no available field
+ if( !field ) {
+ parent.$('.acf-button:last').trigger('click');
+ field = getNext( this, parent );
+ }
+
+ // render
+ if( field ) {
+ field.render( attachment );
+ }
+ },
+
+ selectAttachment: function(){
+
+ // vars
+ var parent = this.parent();
+ var multiple = (parent && parent.get('type') === 'repeater');
+
+ // new frame
+ var frame = acf.newMediaPopup({
+ mode: 'select',
+ type: 'image',
+ title: acf.__('Select Image'),
+ field: this.get('key'),
+ multiple: multiple,
+ library: this.get('library'),
+ allowedTypes: this.get('mime_types'),
+ select: $.proxy(function( attachment, i ) {
+ if( i > 0 ) {
+ this.append( attachment, parent );
+ } else {
+ this.render( attachment );
+ }
+ }, this)
+ });
+ },
+
+ editAttachment: function(){
+
+ // vars
+ var val = this.val();
+
+ // bail early if no val
+ if( !val ) return;
+
+ // popup
+ var frame = acf.newMediaPopup({
+ mode: 'edit',
+ title: acf.__('Edit Image'),
+ button: acf.__('Update Image'),
+ attachment: val,
+ field: this.get('key'),
+ select: $.proxy(function( attachment, i ) {
+ this.render( attachment );
+ }, this)
+ });
+ },
+
+ removeAttachment: function(){
+ this.render( false );
+ },
+
+ onClickAdd: function( e, $el ){
+ this.selectAttachment();
+ },
+
+ onClickEdit: function( e, $el ){
+ this.editAttachment();
+ },
+
+ onClickRemove: function( e, $el ){
+ this.removeAttachment();
+ },
+
+ onChange: function( e, $el ){
+ var $hiddenInput = this.$input();
+
+ acf.getFileInputData($el, function( data ){
+ $hiddenInput.val( $.param(data) );
+ });
+ }
+ });
+
+ acf.registerFieldType( Field );
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'image',
- $control: function () {
- return this.$('.acf-image-uploader');
- },
- $input: function () {
- return this.$('input[type="hidden"]');
- },
- events: {
- 'click a[data-name="add"]': 'onClickAdd',
- 'click a[data-name="edit"]': 'onClickEdit',
- 'click a[data-name="remove"]': 'onClickRemove',
- 'change input[type="file"]': 'onChange'
- },
- initialize: function () {
- // add attribute to form
- if (this.get('uploader') === 'basic') {
- this.$el.closest('form').attr('enctype', 'multipart/form-data');
- }
- },
- validateAttachment: function (attachment) {
- // Use WP attachment attributes when available.
- if (attachment && attachment.attributes) {
- attachment = attachment.attributes;
- } // Apply defaults.
-
-
- attachment = acf.parseArgs(attachment, {
- id: 0,
- url: '',
- alt: '',
- title: '',
- caption: '',
- description: '',
- width: 0,
- height: 0
- }); // Override with "preview size".
-
- var size = acf.isget(attachment, 'sizes', this.get('preview_size'));
-
- if (size) {
- attachment.url = size.url;
- attachment.width = size.width;
- attachment.height = size.height;
- } // Return.
-
-
- return attachment;
- },
- render: function (attachment) {
- attachment = this.validateAttachment(attachment); // Update DOM.
-
- this.$('img').attr({
- src: attachment.url,
- alt: attachment.alt
- });
-
- if (attachment.id) {
- this.val(attachment.id);
- this.$control().addClass('has-value');
- } else {
- this.val('');
- this.$control().removeClass('has-value');
- }
- },
- // create a new repeater row and render value
- append: function (attachment, parent) {
- // create function to find next available field within parent
- var getNext = function (field, parent) {
- // find existing file fields within parent
- var fields = acf.getFields({
- key: field.get('key'),
- parent: parent.$el
- }); // find the first field with no value
-
- for (var i = 0; i < fields.length; i++) {
- if (!fields[i].val()) {
- return fields[i];
- }
- } // return
-
-
- return false;
- }; // find existing file fields within parent
-
-
- var field = getNext(this, parent); // add new row if no available field
-
- if (!field) {
- parent.$('.acf-button:last').trigger('click');
- field = getNext(this, parent);
- } // render
-
-
- if (field) {
- field.render(attachment);
- }
- },
- selectAttachment: function () {
- // vars
- var parent = this.parent();
- var multiple = parent && parent.get('type') === 'repeater'; // new frame
-
- var frame = acf.newMediaPopup({
- mode: 'select',
- type: 'image',
- title: acf.__('Select Image'),
- field: this.get('key'),
- multiple: multiple,
- library: this.get('library'),
- allowedTypes: this.get('mime_types'),
- select: $.proxy(function (attachment, i) {
- if (i > 0) {
- this.append(attachment, parent);
- } else {
- this.render(attachment);
- }
- }, this)
- });
- },
- editAttachment: function () {
- // vars
- var val = this.val(); // bail early if no val
-
- if (!val) return; // popup
-
- var frame = acf.newMediaPopup({
- mode: 'edit',
- title: acf.__('Edit Image'),
- button: acf.__('Update Image'),
- attachment: val,
- field: this.get('key'),
- select: $.proxy(function (attachment, i) {
- this.render(attachment);
- }, this)
- });
- },
- removeAttachment: function () {
- this.render(false);
- },
- onClickAdd: function (e, $el) {
- this.selectAttachment();
- },
- onClickEdit: function (e, $el) {
- this.editAttachment();
- },
- onClickRemove: function (e, $el) {
- this.removeAttachment();
- },
- onChange: function (e, $el) {
- var $hiddenInput = this.$input();
- acf.getFileInputData($el, function (data) {
- $hiddenInput.val($.param(data));
- });
- }
- });
- acf.registerFieldType(Field);
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.models.ImageField.extend({
- type: 'file',
- $control: function () {
- return this.$('.acf-file-uploader');
- },
- $input: function () {
- return this.$('input[type="hidden"]');
- },
- validateAttachment: function (attachment) {
- // defaults
- attachment = attachment || {}; // WP attachment
-
- if (attachment.id !== undefined) {
- attachment = attachment.attributes;
- } // args
-
-
- attachment = acf.parseArgs(attachment, {
- url: '',
- alt: '',
- title: '',
- filename: '',
- filesizeHumanReadable: '',
- icon: '/wp-includes/images/media/default.png'
- }); // return
-
- return attachment;
- },
- render: function (attachment) {
- // vars
- attachment = this.validateAttachment(attachment); // update image
-
- this.$('img').attr({
- src: attachment.icon,
- alt: attachment.alt,
- title: attachment.title
- }); // update elements
-
- this.$('[data-name="title"]').text(attachment.title);
- this.$('[data-name="filename"]').text(attachment.filename).attr('href', attachment.url);
- this.$('[data-name="filesize"]').text(attachment.filesizeHumanReadable); // vars
-
- var val = attachment.id || ''; // update val
-
- acf.val(this.$input(), val); // update class
-
- if (val) {
- this.$control().addClass('has-value');
- } else {
- this.$control().removeClass('has-value');
- }
- },
- selectAttachment: function () {
- // vars
- var parent = this.parent();
- var multiple = parent && parent.get('type') === 'repeater'; // new frame
-
- var frame = acf.newMediaPopup({
- mode: 'select',
- title: acf.__('Select File'),
- field: this.get('key'),
- multiple: multiple,
- library: this.get('library'),
- allowedTypes: this.get('mime_types'),
- select: $.proxy(function (attachment, i) {
- if (i > 0) {
- this.append(attachment, parent);
- } else {
- this.render(attachment);
- }
- }, this)
- });
- },
- editAttachment: function () {
- // vars
- var val = this.val(); // bail early if no val
-
- if (!val) {
- return false;
- } // popup
-
-
- var frame = acf.newMediaPopup({
- mode: 'edit',
- title: acf.__('Edit File'),
- button: acf.__('Update File'),
- attachment: val,
- field: this.get('key'),
- select: $.proxy(function (attachment, i) {
- this.render(attachment);
- }, this)
- });
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.models.ImageField.extend({
+
+ type: 'file',
+
+ $control: function(){
+ return this.$('.acf-file-uploader');
+ },
+
+ $input: function(){
+ return this.$('input[type="hidden"]');
+ },
+
+ validateAttachment: function( attachment ){
+
+ // defaults
+ attachment = attachment || {};
+
+ // WP attachment
+ if( attachment.id !== undefined ) {
+ attachment = attachment.attributes;
+ }
+
+ // args
+ attachment = acf.parseArgs(attachment, {
+ url: '',
+ alt: '',
+ title: '',
+ filename: '',
+ filesizeHumanReadable: '',
+ icon: '/wp-includes/images/media/default.png'
+ });
+
+ // return
+ return attachment;
+ },
+
+ render: function( attachment ){
+
+ // vars
+ attachment = this.validateAttachment( attachment );
+
+ // update image
+ this.$('img').attr({
+ src: attachment.icon,
+ alt: attachment.alt,
+ title: attachment.title
+ });
+
+ // update elements
+ this.$('[data-name="title"]').text( attachment.title );
+ this.$('[data-name="filename"]').text( attachment.filename ).attr( 'href', attachment.url );
+ this.$('[data-name="filesize"]').text( attachment.filesizeHumanReadable );
+
+ // vars
+ var val = attachment.id || '';
+
+ // update val
+ acf.val( this.$input(), val );
+
+ // update class
+ if( val ) {
+ this.$control().addClass('has-value');
+ } else {
+ this.$control().removeClass('has-value');
+ }
+ },
+
+ selectAttachment: function(){
+
+ // vars
+ var parent = this.parent();
+ var multiple = (parent && parent.get('type') === 'repeater');
+
+ // new frame
+ var frame = acf.newMediaPopup({
+ mode: 'select',
+ title: acf.__('Select File'),
+ field: this.get('key'),
+ multiple: multiple,
+ library: this.get('library'),
+ allowedTypes: this.get('mime_types'),
+ select: $.proxy(function( attachment, i ) {
+ if( i > 0 ) {
+ this.append( attachment, parent );
+ } else {
+ this.render( attachment );
+ }
+ }, this)
+ });
+ },
+
+ editAttachment: function(){
+
+ // vars
+ var val = this.val();
+
+ // bail early if no val
+ if( !val ) {
+ return false;
+ }
+
+ // popup
+ var frame = acf.newMediaPopup({
+ mode: 'edit',
+ title: acf.__('Edit File'),
+ button: acf.__('Update File'),
+ attachment: val,
+ field: this.get('key'),
+ select: $.proxy(function( attachment, i ) {
+ this.render( attachment );
+ }, this)
+ });
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'link',
+
+ events: {
+ 'click a[data-name="add"]': 'onClickEdit',
+ 'click a[data-name="edit"]': 'onClickEdit',
+ 'click a[data-name="remove"]': 'onClickRemove',
+ 'change .link-node': 'onChange',
+ },
+
+ $control: function(){
+ return this.$('.acf-link');
+ },
+
+ $node: function(){
+ return this.$('.link-node');
+ },
+
+ getValue: function(){
+
+ // vars
+ var $node = this.$node();
+
+ // return false if empty
+ if( !$node.attr('href') ) {
+ return false;
+ }
+
+ // return
+ return {
+ title: $node.html(),
+ url: $node.attr('href'),
+ target: $node.attr('target')
+ };
+ },
+
+ setValue: function( val ){
+
+ // default
+ val = acf.parseArgs(val, {
+ title: '',
+ url: '',
+ target: ''
+ });
+
+ // vars
+ var $div = this.$control();
+ var $node = this.$node();
+
+ // remove class
+ $div.removeClass('-value -external');
+
+ // add class
+ if( val.url ) $div.addClass('-value');
+ if( val.target === '_blank' ) $div.addClass('-external');
+
+ // update text
+ this.$('.link-title').html( val.title );
+ this.$('.link-url').attr('href', val.url).html( val.url );
+
+ // update node
+ $node.html(val.title);
+ $node.attr('href', val.url);
+ $node.attr('target', val.target);
+
+ // update inputs
+ this.$('.input-title').val( val.title );
+ this.$('.input-target').val( val.target );
+ this.$('.input-url').val( val.url ).trigger('change');
+ },
+
+ onClickEdit: function( e, $el ){
+ acf.wpLink.open( this.$node() );
+ },
+
+ onClickRemove: function( e, $el ){
+ this.setValue( false );
+ },
+
+ onChange: function( e, $el ){
+
+ // get the changed value
+ var val = this.getValue();
+
+ // update inputs
+ this.setValue(val);
+ }
+
+ });
+
+ acf.registerFieldType( Field );
+
+
+ // manager
+ acf.wpLink = new acf.Model({
+
+ getNodeValue: function(){
+ var $node = this.get('node');
+ return {
+ title: acf.decode( $node.html() ),
+ url: $node.attr('href'),
+ target: $node.attr('target')
+ };
+ },
+
+ setNodeValue: function( val ){
+ var $node = this.get('node');
+ $node.text( val.title );
+ $node.attr('href', val.url);
+ $node.attr('target', val.target);
+ $node.trigger('change');
+ },
+
+ getInputValue: function(){
+ return {
+ title: $('#wp-link-text').val(),
+ url: $('#wp-link-url').val(),
+ target: $('#wp-link-target').prop('checked') ? '_blank' : ''
+ };
+ },
+
+ setInputValue: function( val ){
+ $('#wp-link-text').val( val.title );
+ $('#wp-link-url').val( val.url );
+ $('#wp-link-target').prop('checked', val.target === '_blank' );
+ },
+
+ open: function( $node ){
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'link',
- events: {
- 'click a[data-name="add"]': 'onClickEdit',
- 'click a[data-name="edit"]': 'onClickEdit',
- 'click a[data-name="remove"]': 'onClickRemove',
- 'change .link-node': 'onChange'
- },
- $control: function () {
- return this.$('.acf-link');
- },
- $node: function () {
- return this.$('.link-node');
- },
- getValue: function () {
- // vars
- var $node = this.$node(); // return false if empty
+ // add events
+ this.on('wplink-open', 'onOpen');
+ this.on('wplink-close', 'onClose');
+
+ // set node
+ this.set('node', $node);
+
+ // create textarea
+ var $textarea = $('');
+ $('body').append( $textarea );
+
+ // vars
+ var val = this.getNodeValue();
+
+ // open popup
+ wpLink.open( 'acf-link-textarea', val.url, val.title, null );
+ },
+
+ onOpen: function(){
- if (!$node.attr('href')) {
- return false;
- } // return
+ // always show title (WP will hide title if empty)
+ $('#wp-link-wrap').addClass('has-text-field');
+
+ // set inputs
+ var val = this.getNodeValue();
+ this.setInputValue( val );
+ // Update button text.
+ if( val.url && wpLinkL10n ) {
+ $('#wp-link-submit').val( wpLinkL10n.update );
+ }
+ },
+
+ close: function(){
+ wpLink.close();
+ },
+
+ onClose: function(){
+
+ // Bail early if no node.
+ // Needed due to WP triggering this event twice.
+ if( !this.has('node') ) {
+ return false;
+ }
- return {
- title: $node.html(),
- url: $node.attr('href'),
- target: $node.attr('target')
- };
- },
- setValue: function (val) {
- // default
- val = acf.parseArgs(val, {
- title: '',
- url: '',
- target: ''
- }); // vars
+ // Determine context.
+ var $submit = $('#wp-link-submit');
+ var isSubmit = ( $submit.is(':hover') || $submit.is(':focus') );
+
+ // Set value
+ if( isSubmit ) {
+ var val = this.getInputValue();
+ this.setNodeValue( val );
+ }
+
+ // Cleanup.
+ this.off('wplink-open');
+ this.off('wplink-close');
+ $('#acf-link-textarea').remove();
+ this.set('node', null);
+ }
+ });
- var $div = this.$control();
- var $node = this.$node(); // remove class
-
- $div.removeClass('-value -external'); // add class
-
- if (val.url) $div.addClass('-value');
- if (val.target === '_blank') $div.addClass('-external'); // update text
-
- this.$('.link-title').html(val.title);
- this.$('.link-url').attr('href', val.url).html(val.url); // update node
-
- $node.html(val.title);
- $node.attr('href', val.url);
- $node.attr('target', val.target); // update inputs
-
- this.$('.input-title').val(val.title);
- this.$('.input-target').val(val.target);
- this.$('.input-url').val(val.url).trigger('change');
- },
- onClickEdit: function (e, $el) {
- acf.wpLink.open(this.$node());
- },
- onClickRemove: function (e, $el) {
- this.setValue(false);
- },
- onChange: function (e, $el) {
- // get the changed value
- var val = this.getValue(); // update inputs
-
- this.setValue(val);
- }
- });
- acf.registerFieldType(Field); // manager
-
- acf.wpLink = new acf.Model({
- getNodeValue: function () {
- var $node = this.get('node');
- return {
- title: acf.decode($node.html()),
- url: $node.attr('href'),
- target: $node.attr('target')
- };
- },
- setNodeValue: function (val) {
- var $node = this.get('node');
- $node.text(val.title);
- $node.attr('href', val.url);
- $node.attr('target', val.target);
- $node.trigger('change');
- },
- getInputValue: function () {
- return {
- title: $('#wp-link-text').val(),
- url: $('#wp-link-url').val(),
- target: $('#wp-link-target').prop('checked') ? '_blank' : ''
- };
- },
- setInputValue: function (val) {
- $('#wp-link-text').val(val.title);
- $('#wp-link-url').val(val.url);
- $('#wp-link-target').prop('checked', val.target === '_blank');
- },
- open: function ($node) {
- // add events
- this.on('wplink-open', 'onOpen');
- this.on('wplink-close', 'onClose'); // set node
-
- this.set('node', $node); // create textarea
-
- var $textarea = $('');
- $('body').append($textarea); // vars
-
- var val = this.getNodeValue(); // open popup
-
- wpLink.open('acf-link-textarea', val.url, val.title, null);
- },
- onOpen: function () {
- // always show title (WP will hide title if empty)
- $('#wp-link-wrap').addClass('has-text-field'); // set inputs
-
- var val = this.getNodeValue();
- this.setInputValue(val); // Update button text.
-
- if (val.url && wpLinkL10n) {
- $('#wp-link-submit').val(wpLinkL10n.update);
- }
- },
- close: function () {
- wpLink.close();
- },
- onClose: function () {
- // Bail early if no node.
- // Needed due to WP triggering this event twice.
- if (!this.has('node')) {
- return false;
- } // Determine context.
-
-
- var $submit = $('#wp-link-submit');
- var isSubmit = $submit.is(':hover') || $submit.is(':focus'); // Set value
-
- if (isSubmit) {
- var val = this.getInputValue();
- this.setNodeValue(val);
- } // Cleanup.
-
-
- this.off('wplink-open');
- this.off('wplink-close');
- $('#acf-link-textarea').remove();
- this.set('node', null);
- }
- });
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'oembed',
+
+ events: {
+ 'click [data-name="clear-button"]': 'onClickClear',
+ 'keypress .input-search': 'onKeypressSearch',
+ 'keyup .input-search': 'onKeyupSearch',
+ 'change .input-search': 'onChangeSearch'
+ },
+
+ $control: function(){
+ return this.$('.acf-oembed');
+ },
+
+ $input: function(){
+ return this.$('.input-value');
+ },
+
+ $search: function(){
+ return this.$('.input-search');
+ },
+
+ getValue: function(){
+ return this.$input().val();
+ },
+
+ getSearchVal: function(){
+ return this.$search().val();
+ },
+
+ setValue: function( val ){
+
+ // class
+ if( val ) {
+ this.$control().addClass('has-value');
+ } else {
+ this.$control().removeClass('has-value');
+ }
+
+ acf.val( this.$input(), val );
+ },
+
+ showLoading: function( show ){
+ acf.showLoading( this.$('.canvas') );
+ },
+
+ hideLoading: function(){
+ acf.hideLoading( this.$('.canvas') );
+ },
+
+ maybeSearch: function(){
+
+ // vars
+ var prevUrl = this.val();
+ var url = this.getSearchVal();
+
+ // no value
+ if( !url ) {
+ return this.clear();
+ }
+
+ // fix missing 'http://' - causes the oembed code to error and fail
+ if( url.substr(0, 4) != 'http' ) {
+ url = 'http://' + url;
+ }
+
+ // bail early if no change
+ if( url === prevUrl ) return;
+
+ // clear existing timeout
+ var timeout = this.get('timeout');
+ if( timeout ) {
+ clearTimeout( timeout );
+ }
+
+ // set new timeout
+ var callback = $.proxy(this.search, this, url);
+ this.set('timeout', setTimeout(callback, 300));
+
+ },
+
+ search: function( url ){
+
+ // ajax
+ var ajaxData = {
+ action: 'acf/fields/oembed/search',
+ s: url,
+ field_key: this.get('key')
+ };
+
+ // clear existing timeout
+ var xhr = this.get('xhr');
+ if( xhr ) {
+ xhr.abort();
+ }
+
+ // loading
+ this.showLoading();
+
+ // query
+ var xhr = $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxData),
+ type: 'post',
+ dataType: 'json',
+ context: this,
+ success: function( json ){
+
+ // error
+ if( !json || !json.html ) {
+ json = {
+ url: false,
+ html: ''
+ }
+ }
+
+ // update vars
+ this.val( json.url );
+ this.$('.canvas-media').html( json.html );
+ },
+ complete: function(){
+ this.hideLoading();
+ }
+ });
+
+ this.set('xhr', xhr);
+ },
+
+ clear: function(){
+ this.val('');
+ this.$search().val('');
+ this.$('.canvas-media').html('');
+ },
+
+ onClickClear: function( e, $el ){
+ this.clear();
+ },
+
+ onKeypressSearch: function( e, $el ){
+ if( e.which == 13 ) {
+ e.preventDefault();
+ this.maybeSearch();
+ }
+ },
+
+ onKeyupSearch: function( e, $el ){
+ if( $el.val() ) {
+ this.maybeSearch();
+ }
+ },
+
+ onChangeSearch: function( e, $el ){
+ this.maybeSearch();
+ }
+
+ });
+
+ acf.registerFieldType( Field );
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'oembed',
- events: {
- 'click [data-name="clear-button"]': 'onClickClear',
- 'keypress .input-search': 'onKeypressSearch',
- 'keyup .input-search': 'onKeyupSearch',
- 'change .input-search': 'onChangeSearch'
- },
- $control: function () {
- return this.$('.acf-oembed');
- },
- $input: function () {
- return this.$('.input-value');
- },
- $search: function () {
- return this.$('.input-search');
- },
- getValue: function () {
- return this.$input().val();
- },
- getSearchVal: function () {
- return this.$search().val();
- },
- setValue: function (val) {
- // class
- if (val) {
- this.$control().addClass('has-value');
- } else {
- this.$control().removeClass('has-value');
- }
-
- acf.val(this.$input(), val);
- },
- showLoading: function (show) {
- acf.showLoading(this.$('.canvas'));
- },
- hideLoading: function () {
- acf.hideLoading(this.$('.canvas'));
- },
- maybeSearch: function () {
- // vars
- var prevUrl = this.val();
- var url = this.getSearchVal(); // no value
-
- if (!url) {
- return this.clear();
- } // fix missing 'http://' - causes the oembed code to error and fail
-
-
- if (url.substr(0, 4) != 'http') {
- url = 'http://' + url;
- } // bail early if no change
-
-
- if (url === prevUrl) return; // clear existing timeout
-
- var timeout = this.get('timeout');
-
- if (timeout) {
- clearTimeout(timeout);
- } // set new timeout
-
-
- var callback = $.proxy(this.search, this, url);
- this.set('timeout', setTimeout(callback, 300));
- },
- search: function (url) {
- // ajax
- var ajaxData = {
- action: 'acf/fields/oembed/search',
- s: url,
- field_key: this.get('key')
- }; // clear existing timeout
-
- var xhr = this.get('xhr');
-
- if (xhr) {
- xhr.abort();
- } // loading
-
-
- this.showLoading(); // query
-
- var xhr = $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'json',
- context: this,
- success: function (json) {
- // error
- if (!json || !json.html) {
- json = {
- url: false,
- html: ''
- };
- } // update vars
-
-
- this.val(json.url);
- this.$('.canvas-media').html(json.html);
- },
- complete: function () {
- this.hideLoading();
- }
- });
- this.set('xhr', xhr);
- },
- clear: function () {
- this.val('');
- this.$search().val('');
- this.$('.canvas-media').html('');
- },
- onClickClear: function (e, $el) {
- this.clear();
- },
- onKeypressSearch: function (e, $el) {
- if (e.which == 13) {
- e.preventDefault();
- this.maybeSearch();
- }
- },
- onKeyupSearch: function (e, $el) {
- if ($el.val()) {
- this.maybeSearch();
- }
- },
- onChangeSearch: function (e, $el) {
- this.maybeSearch();
- }
- });
- acf.registerFieldType(Field);
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'radio',
+
+ events: {
+ 'click input[type="radio"]': 'onClick',
+ },
+
+ $control: function(){
+ return this.$('.acf-radio-list');
+ },
+
+ $input: function(){
+ return this.$('input:checked');
+ },
+
+ $inputText: function(){
+ return this.$('input[type="text"]');
+ },
+
+ getValue: function(){
+ var val = this.$input().val();
+ if( val === 'other' && this.get('other_choice') ) {
+ val = this.$inputText().val();
+ }
+ return val;
+ },
+
+ onClick: function( e, $el ){
+
+ // vars
+ var $label = $el.parent('label');
+ var selected = $label.hasClass('selected');
+ var val = $el.val();
+
+ // remove previous selected
+ this.$('.selected').removeClass('selected');
+
+ // add active class
+ $label.addClass('selected');
+
+ // allow null
+ if( this.get('allow_null') && selected ) {
+ $label.removeClass('selected');
+ $el.prop('checked', false).trigger('change');
+ val = false;
+ }
+
+ // other
+ if( this.get('other_choice') ) {
+
+ // enable
+ if( val === 'other' ) {
+ this.$inputText().prop('disabled', false);
+
+ // disable
+ } else {
+ this.$inputText().prop('disabled', true);
+ }
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'radio',
- events: {
- 'click input[type="radio"]': 'onClick'
- },
- $control: function () {
- return this.$('.acf-radio-list');
- },
- $input: function () {
- return this.$('input:checked');
- },
- $inputText: function () {
- return this.$('input[type="text"]');
- },
- getValue: function () {
- var val = this.$input().val();
-
- if (val === 'other' && this.get('other_choice')) {
- val = this.$inputText().val();
- }
-
- return val;
- },
- onClick: function (e, $el) {
- // vars
- var $label = $el.parent('label');
- var selected = $label.hasClass('selected');
- var val = $el.val(); // remove previous selected
-
- this.$('.selected').removeClass('selected'); // add active class
-
- $label.addClass('selected'); // allow null
-
- if (this.get('allow_null') && selected) {
- $label.removeClass('selected');
- $el.prop('checked', false).trigger('change');
- val = false;
- } // other
-
-
- if (this.get('other_choice')) {
- // enable
- if (val === 'other') {
- this.$inputText().prop('disabled', false); // disable
- } else {
- this.$inputText().prop('disabled', true);
- }
- }
- }
- });
- acf.registerFieldType(Field);
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'range',
- events: {
- 'input input[type="range"]': 'onChange',
- 'change input': 'onChange'
- },
- $input: function () {
- return this.$('input[type="range"]');
- },
- $inputAlt: function () {
- return this.$('input[type="number"]');
- },
- setValue: function (val) {
- this.busy = true; // Update range input (with change).
-
- acf.val(this.$input(), val); // Update alt input (without change).
- // Read in input value to inherit min/max validation.
-
- acf.val(this.$inputAlt(), this.$input().val(), true);
- this.busy = false;
- },
- onChange: function (e, $el) {
- if (!this.busy) {
- this.setValue($el.val());
- }
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'range',
+
+ events: {
+ 'input input[type="range"]': 'onChange',
+ 'change input': 'onChange'
+ },
+
+ $input: function(){
+ return this.$('input[type="range"]');
+ },
+
+ $inputAlt: function(){
+ return this.$('input[type="number"]');
+ },
+
+ setValue: function( val ){
+ this.busy = true;
+
+ // Update range input (with change).
+ acf.val( this.$input(), val );
+
+ // Update alt input (without change).
+ // Read in input value to inherit min/max validation.
+ acf.val( this.$inputAlt(), this.$input().val(), true );
+
+ this.busy = false;
+ },
+
+ onChange: function( e, $el ){
+ if( !this.busy ) {
+ this.setValue( $el.val() );
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'relationship',
- events: {
- 'keypress [data-filter]': 'onKeypressFilter',
- 'change [data-filter]': 'onChangeFilter',
- 'keyup [data-filter]': 'onChangeFilter',
- 'click .choices-list .acf-rel-item': 'onClickAdd',
- 'click [data-name="remove_item"]': 'onClickRemove'
- },
- $control: function () {
- return this.$('.acf-relationship');
- },
- $list: function (list) {
- return this.$('.' + list + '-list');
- },
- $listItems: function (list) {
- return this.$list(list).find('.acf-rel-item');
- },
- $listItem: function (list, id) {
- return this.$list(list).find('.acf-rel-item[data-id="' + id + '"]');
- },
- getValue: function () {
- var val = [];
- this.$listItems('values').each(function () {
- val.push($(this).data('id'));
- });
- return val.length ? val : false;
- },
- newChoice: function (props) {
- return ['', '' + props.text + ' ', ' '].join('');
- },
- newValue: function (props) {
- return ['', ' ', '' + props.text, ' ', ' ', ' '].join('');
- },
- initialize: function () {
- // Delay initialization until "interacted with" or "in view".
- var delayed = this.proxy(acf.once(function () {
- // Add sortable.
- this.$list('values').sortable({
- items: 'li',
- forceHelperSize: true,
- forcePlaceholderSize: true,
- scroll: true,
- update: this.proxy(function () {
- this.$input().trigger('change');
- })
- }); // Avoid browser remembering old scroll position and add event.
-
- this.$list('choices').scrollTop(0).on('scroll', this.proxy(this.onScrollChoices)); // Fetch choices.
-
- this.fetch();
- })); // Bind "interacted with".
-
- this.$el.one('mouseover', delayed);
- this.$el.one('focus', 'input', delayed); // Bind "in view".
-
- acf.onceInView(this.$el, delayed);
- },
- onScrollChoices: function (e) {
- // bail early if no more results
- if (this.get('loading') || !this.get('more')) {
- return;
- } // Scrolled to bottom
-
-
- var $list = this.$list('choices');
- var scrollTop = Math.ceil($list.scrollTop());
- var scrollHeight = Math.ceil($list[0].scrollHeight);
- var innerHeight = Math.ceil($list.innerHeight());
- var paged = this.get('paged') || 1;
-
- if (scrollTop + innerHeight >= scrollHeight) {
- // update paged
- this.set('paged', paged + 1); // fetch
-
- this.fetch();
- }
- },
- onKeypressFilter: function (e, $el) {
- // don't submit form
- if (e.which == 13) {
- e.preventDefault();
- }
- },
- onChangeFilter: function (e, $el) {
- // vars
- var val = $el.val();
- var filter = $el.data('filter'); // Bail early if filter has not changed
-
- if (this.get(filter) === val) {
- return;
- } // update attr
-
-
- this.set(filter, val); // reset paged
-
- this.set('paged', 1); // fetch
-
- if ($el.is('select')) {
- this.fetch(); // search must go through timeout
- } else {
- this.maybeFetch();
- }
- },
- onClickAdd: function (e, $el) {
- // vars
- var val = this.val();
- var max = parseInt(this.get('max')); // can be added?
-
- if ($el.hasClass('disabled')) {
- return false;
- } // validate
-
-
- if (max > 0 && val && val.length >= max) {
- // add notice
- this.showNotice({
- text: acf.__('Maximum values reached ( {max} values )').replace('{max}', max),
- type: 'warning'
- });
- return false;
- } // disable
-
-
- $el.addClass('disabled'); // add
-
- var html = this.newValue({
- id: $el.data('id'),
- text: $el.html()
- });
- this.$list('values').append(html); // trigger change
-
- this.$input().trigger('change');
- },
- onClickRemove: function (e, $el) {
- // Prevent default here because generic handler wont be triggered.
- e.preventDefault(); // vars
-
- var $span = $el.parent();
- var $li = $span.parent();
- var id = $span.data('id'); // remove value
-
- $li.remove(); // show choice
-
- this.$listItem('choices', id).removeClass('disabled'); // trigger change
-
- this.$input().trigger('change');
- },
- maybeFetch: function () {
- // vars
- var timeout = this.get('timeout'); // abort timeout
-
- if (timeout) {
- clearTimeout(timeout);
- } // fetch
-
-
- timeout = this.setTimeout(this.fetch, 300);
- this.set('timeout', timeout);
- },
- getAjaxData: function () {
- // load data based on element attributes
- var ajaxData = this.$control().data();
-
- for (var name in ajaxData) {
- ajaxData[name] = this.get(name);
- } // extra
-
-
- ajaxData.action = 'acf/fields/relationship/query';
- ajaxData.field_key = this.get('key'); // Filter.
-
- ajaxData = acf.applyFilters('relationship_ajax_data', ajaxData, this); // return
-
- return ajaxData;
- },
- fetch: function () {
- // abort XHR if this field is already loading AJAX data
- var xhr = this.get('xhr');
-
- if (xhr) {
- xhr.abort();
- } // add to this.o
-
-
- var ajaxData = this.getAjaxData(); // clear html if is new query
-
- var $choiceslist = this.$list('choices');
-
- if (ajaxData.paged == 1) {
- $choiceslist.html('');
- } // loading
-
-
- var $loading = $(' ' + acf.__('Loading') + ' ');
- $choiceslist.append($loading);
- this.set('loading', true); // callback
-
- var onComplete = function () {
- this.set('loading', false);
- $loading.remove();
- };
-
- var onSuccess = function (json) {
- // no results
- if (!json || !json.results || !json.results.length) {
- // prevent pagination
- this.set('more', false); // add message
-
- if (this.get('paged') == 1) {
- this.$list('choices').append('' + acf.__('No matches found') + ' ');
- } // return
-
-
- return;
- } // set more (allows pagination scroll)
-
-
- this.set('more', json.more); // get new results
-
- var html = this.walkChoices(json.results);
- var $html = $(html); // apply .disabled to left li's
-
- var val = this.val();
-
- if (val && val.length) {
- val.map(function (id) {
- $html.find('.acf-rel-item[data-id="' + id + '"]').addClass('disabled');
- });
- } // append
-
-
- $choiceslist.append($html); // merge together groups
-
- var $prevLabel = false;
- var $prevList = false;
- $choiceslist.find('.acf-rel-label').each(function () {
- var $label = $(this);
- var $list = $label.siblings('ul');
-
- if ($prevLabel && $prevLabel.text() == $label.text()) {
- $prevList.append($list.children());
- $(this).parent().remove();
- return;
- } // update vars
-
-
- $prevLabel = $label;
- $prevList = $list;
- });
- }; // get results
-
-
- var xhr = $.ajax({
- url: acf.get('ajaxurl'),
- dataType: 'json',
- type: 'post',
- data: acf.prepareForAjax(ajaxData),
- context: this,
- success: onSuccess,
- complete: onComplete
- }); // set
-
- this.set('xhr', xhr);
- },
- walkChoices: function (data) {
- // walker
- var walk = function (data) {
- // vars
- var html = ''; // is array
-
- if ($.isArray(data)) {
- data.map(function (item) {
- html += walk(item);
- }); // is item
- } else if ($.isPlainObject(data)) {
- // group
- if (data.children !== undefined) {
- html += '' + acf.escHtml(data.text) + ' ';
- html += walk(data.children);
- html += ' '; // single
- } else {
- html += '' + acf.escHtml(data.text) + ' ';
- }
- } // return
-
-
- return html;
- };
-
- return walk(data);
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'relationship',
+
+ events: {
+ 'keypress [data-filter]': 'onKeypressFilter',
+ 'change [data-filter]': 'onChangeFilter',
+ 'keyup [data-filter]': 'onChangeFilter',
+ 'click .choices-list .acf-rel-item': 'onClickAdd',
+ 'click [data-name="remove_item"]': 'onClickRemove',
+ },
+
+ $control: function(){
+ return this.$('.acf-relationship');
+ },
+
+ $list: function( list ) {
+ return this.$('.' + list + '-list');
+ },
+
+ $listItems: function( list ) {
+ return this.$list( list ).find('.acf-rel-item');
+ },
+
+ $listItem: function( list, id ) {
+ return this.$list( list ).find('.acf-rel-item[data-id="' + id + '"]');
+ },
+
+ getValue: function(){
+ var val = [];
+ this.$listItems('values').each(function(){
+ val.push( $(this).data('id') );
+ });
+ return val.length ? val : false;
+ },
+
+ newChoice: function( props ){
+ return [
+ '',
+ '' + props.text + ' ',
+ ' '
+ ].join('');
+ },
+
+ newValue: function( props ){
+ return [
+ '',
+ ' ',
+ '' + props.text,
+ ' ',
+ ' ',
+ ' '
+ ].join('');
+ },
+
+ initialize: function(){
+
+ // Delay initialization until "interacted with" or "in view".
+ var delayed = this.proxy(acf.once(function(){
+
+ // Add sortable.
+ this.$list('values').sortable({
+ items: 'li',
+ forceHelperSize: true,
+ forcePlaceholderSize: true,
+ scroll: true,
+ update: this.proxy(function(){
+ this.$input().trigger('change');
+ })
+ });
+
+ // Avoid browser remembering old scroll position and add event.
+ this.$list('choices').scrollTop(0).on('scroll', this.proxy(this.onScrollChoices));
+
+ // Fetch choices.
+ this.fetch();
+
+ }));
+
+ // Bind "interacted with".
+ this.$el.one( 'mouseover', delayed );
+ this.$el.one( 'focus', 'input', delayed );
+
+ // Bind "in view".
+ acf.onceInView( this.$el, delayed );
+ },
+
+ onScrollChoices: function(e){
+
+ // bail early if no more results
+ if( this.get('loading') || !this.get('more') ) {
+ return;
+ }
+
+ // Scrolled to bottom
+ var $list = this.$list('choices');
+ var scrollTop = Math.ceil( $list.scrollTop() );
+ var scrollHeight = Math.ceil( $list[0].scrollHeight );
+ var innerHeight = Math.ceil( $list.innerHeight() );
+ var paged = this.get('paged') || 1;
+ if( (scrollTop + innerHeight) >= scrollHeight ) {
+
+ // update paged
+ this.set('paged', (paged+1));
+
+ // fetch
+ this.fetch();
+ }
+ },
+
+ onKeypressFilter: function( e, $el ){
+
+ // don't submit form
+ if( e.which == 13 ) {
+ e.preventDefault();
+ }
+ },
+
+ onChangeFilter: function( e, $el ){
+
+ // vars
+ var val = $el.val();
+ var filter = $el.data('filter');
+
+ // Bail early if filter has not changed
+ if( this.get(filter) === val ) {
+ return;
+ }
+
+ // update attr
+ this.set(filter, val);
+
+ // reset paged
+ this.set('paged', 1);
+
+ // fetch
+ if( $el.is('select') ) {
+ this.fetch();
+
+ // search must go through timeout
+ } else {
+ this.maybeFetch();
+ }
+ },
+
+ onClickAdd: function( e, $el ){
+
+ // vars
+ var val = this.val();
+ var max = parseInt( this.get('max') );
+
+ // can be added?
+ if( $el.hasClass('disabled') ) {
+ return false;
+ }
+
+ // validate
+ if( max > 0 && val && val.length >= max ) {
+
+ // add notice
+ this.showNotice({
+ text: acf.__('Maximum values reached ( {max} values )').replace('{max}', max),
+ type: 'warning'
+ });
+ return false;
+ }
+
+ // disable
+ $el.addClass('disabled');
+
+ // add
+ var html = this.newValue({
+ id: $el.data('id'),
+ text: $el.html()
+ });
+ this.$list('values').append( html )
+
+ // trigger change
+ this.$input().trigger('change');
+ },
+
+ onClickRemove: function( e, $el ){
+
+ // Prevent default here because generic handler wont be triggered.
+ e.preventDefault();
+
+ // vars
+ var $span = $el.parent();
+ var $li = $span.parent();
+ var id = $span.data('id');
+
+ // remove value
+ $li.remove();
+
+ // show choice
+ this.$listItem('choices', id).removeClass('disabled');
+
+ // trigger change
+ this.$input().trigger('change');
+ },
+
+ maybeFetch: function(){
+
+ // vars
+ var timeout = this.get('timeout');
+
+ // abort timeout
+ if( timeout ) {
+ clearTimeout( timeout );
+ }
+
+ // fetch
+ timeout = this.setTimeout(this.fetch, 300);
+ this.set('timeout', timeout);
+ },
+
+ getAjaxData: function(){
+
+ // load data based on element attributes
+ var ajaxData = this.$control().data();
+ for( var name in ajaxData ) {
+ ajaxData[ name ] = this.get( name );
+ }
+
+ // extra
+ ajaxData.action = 'acf/fields/relationship/query';
+ ajaxData.field_key = this.get('key');
+
+ // Filter.
+ ajaxData = acf.applyFilters( 'relationship_ajax_data', ajaxData, this );
+
+ // return
+ return ajaxData;
+ },
+
+ fetch: function(){
+
+ // abort XHR if this field is already loading AJAX data
+ var xhr = this.get('xhr');
+ if( xhr ) {
+ xhr.abort();
+ }
+
+ // add to this.o
+ var ajaxData = this.getAjaxData();
+
+ // clear html if is new query
+ var $choiceslist = this.$list( 'choices' );
+ if( ajaxData.paged == 1 ) {
+ $choiceslist.html('');
+ }
+
+ // loading
+ var $loading = $(' ' + acf.__('Loading') + ' ');
+ $choiceslist.append($loading);
+ this.set('loading', true);
+
+ // callback
+ var onComplete = function(){
+ this.set('loading', false);
+ $loading.remove();
+ };
+
+ var onSuccess = function( json ){
+
+ // no results
+ if( !json || !json.results || !json.results.length ) {
+
+ // prevent pagination
+ this.set('more', false);
+
+ // add message
+ if( this.get('paged') == 1 ) {
+ this.$list('choices').append('' + acf.__('No matches found') + ' ');
+ }
+
+ // return
+ return;
+ }
+
+ // set more (allows pagination scroll)
+ this.set('more', json.more );
+
+ // get new results
+ var html = this.walkChoices(json.results);
+ var $html = $( html );
+
+ // apply .disabled to left li's
+ var val = this.val();
+ if( val && val.length ) {
+ val.map(function( id ){
+ $html.find('.acf-rel-item[data-id="' + id + '"]').addClass('disabled');
+ });
+ }
+
+ // append
+ $choiceslist.append( $html );
+
+ // merge together groups
+ var $prevLabel = false;
+ var $prevList = false;
+
+ $choiceslist.find('.acf-rel-label').each(function(){
+
+ var $label = $(this);
+ var $list = $label.siblings('ul');
+
+ if( $prevLabel && $prevLabel.text() == $label.text() ) {
+ $prevList.append( $list.children() );
+ $(this).parent().remove();
+ return;
+ }
+
+ // update vars
+ $prevLabel = $label;
+ $prevList = $list;
+ });
+ };
+
+ // get results
+ var xhr = $.ajax({
+ url: acf.get('ajaxurl'),
+ dataType: 'json',
+ type: 'post',
+ data: acf.prepareForAjax(ajaxData),
+ context: this,
+ success: onSuccess,
+ complete: onComplete
+ });
+
+ // set
+ this.set('xhr', xhr);
+ },
+
+ walkChoices: function( data ){
+
+ // walker
+ var walk = function( data ){
+
+ // vars
+ var html = '';
+
+ // is array
+ if( $.isArray(data) ) {
+ data.map(function(item){
+ html += walk( item );
+ });
+
+ // is item
+ } else if( $.isPlainObject(data) ) {
+
+ // group
+ if( data.children !== undefined ) {
+
+ html += '' + acf.escHtml( data.text ) + ' ';
+ html += walk( data.children );
+ html += ' ';
+
+ // single
+ } else {
+ html += '' + acf.escHtml( data.text ) + ' ';
+ }
+ }
+
+ // return
+ return html;
+ };
+
+ return walk( data );
+ }
+
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'select',
- select2: false,
- wait: 'load',
- events: {
- 'removeField': 'onRemove',
- 'duplicateField': 'onDuplicate'
- },
- $input: function () {
- return this.$('select');
- },
- initialize: function () {
- // vars
- var $select = this.$input(); // inherit data
-
- this.inherit($select); // select2
-
- if (this.get('ui')) {
- // populate ajax_data (allowing custom attribute to already exist)
- var ajaxAction = this.get('ajax_action');
-
- if (!ajaxAction) {
- ajaxAction = 'acf/fields/' + this.get('type') + '/query';
- } // select2
-
-
- this.select2 = acf.newSelect2($select, {
- field: this,
- ajax: this.get('ajax'),
- multiple: this.get('multiple'),
- placeholder: this.get('placeholder'),
- allowNull: this.get('allow_null'),
- ajaxAction: ajaxAction
- });
- }
- },
- onRemove: function () {
- if (this.select2) {
- this.select2.destroy();
- }
- },
- onDuplicate: function (e, $el, $duplicate) {
- if (this.select2) {
- $duplicate.find('.select2-container').remove();
- $duplicate.find('select').removeClass('select2-hidden-accessible');
- }
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'select',
+
+ select2: false,
+
+ wait: 'load',
+
+ events: {
+ 'removeField': 'onRemove',
+ 'duplicateField': 'onDuplicate'
+ },
+
+ $input: function(){
+ return this.$('select');
+ },
+
+ initialize: function(){
+
+ // vars
+ var $select = this.$input();
+
+ // inherit data
+ this.inherit( $select );
+
+ // select2
+ if( this.get('ui') ) {
+
+ // populate ajax_data (allowing custom attribute to already exist)
+ var ajaxAction = this.get('ajax_action');
+ if( !ajaxAction ) {
+ ajaxAction = 'acf/fields/' + this.get('type') + '/query';
+ }
+
+ // select2
+ this.select2 = acf.newSelect2($select, {
+ field: this,
+ ajax: this.get('ajax'),
+ multiple: this.get('multiple'),
+ placeholder: this.get('placeholder'),
+ allowNull: this.get('allow_null'),
+ ajaxAction: ajaxAction,
+ });
+ }
+ },
+
+ onRemove: function(){
+ if( this.select2 ) {
+ this.select2.destroy();
+ }
+ },
+
+ onDuplicate: function( e, $el, $duplicate ){
+ if( this.select2 ) {
+ $duplicate.find('.select2-container').remove();
+ $duplicate.find('select').removeClass('select2-hidden-accessible');
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ // vars
+ var CONTEXT = 'tab';
+
+ var Field = acf.Field.extend({
+
+ type: 'tab',
+
+ wait: '',
+
+ tabs: false,
+
+ tab: false,
+
+ events: {
+ 'duplicateField': 'onDuplicate'
+ },
-(function ($, undefined) {
- // vars
- var CONTEXT = 'tab';
- var Field = acf.Field.extend({
- type: 'tab',
- wait: '',
- tabs: false,
- tab: false,
- events: {
- 'duplicateField': 'onDuplicate'
- },
- findFields: function () {
- return this.$el.nextUntil('.acf-field-tab', '.acf-field');
- },
- getFields: function () {
- return acf.getFields(this.findFields());
- },
- findTabs: function () {
- return this.$el.prevAll('.acf-tab-wrap:first');
- },
- findTab: function () {
- return this.$('.acf-tab-button');
- },
- initialize: function () {
- // bail early if is td
- if (this.$el.is('td')) {
- this.events = {};
- return false;
- } // vars
+ findFields: function(){
+ return this.$el.nextUntil('.acf-field-tab', '.acf-field');
+ },
+
+ getFields: function(){
+ return acf.getFields( this.findFields() );
+ },
+
+ findTabs: function(){
+ return this.$el.prevAll('.acf-tab-wrap:first');
+ },
+
+ findTab: function(){
+ return this.$('.acf-tab-button');
+ },
+
+ initialize: function(){
+
+ // bail early if is td
+ if( this.$el.is('td') ) {
+ this.events = {};
+ return false;
+ }
+
+ // vars
+ var $tabs = this.findTabs();
+ var $tab = this.findTab();
+ var settings = acf.parseArgs($tab.data(), {
+ endpoint: false,
+ placement: '',
+ before: this.$el
+ });
+
+ // create wrap
+ if( !$tabs.length || settings.endpoint ) {
+ this.tabs = new Tabs( settings );
+ } else {
+ this.tabs = $tabs.data('acf');
+ }
+
+ // add tab
+ this.tab = this.tabs.addTab($tab, this);
+ },
+
+ isActive: function(){
+ return this.tab.isActive();
+ },
+
+ showFields: function(){
+
+ // show fields
+ this.getFields().map(function( field ){
+ field.show( this.cid, CONTEXT );
+ field.hiddenByTab = false;
+ }, this);
+
+ },
+
+ hideFields: function(){
+
+ // hide fields
+ this.getFields().map(function( field ){
+ field.hide( this.cid, CONTEXT );
+ field.hiddenByTab = this.tab;
+ }, this);
+
+ },
+
+ show: function( lockKey ){
+ // show field and store result
+ var visible = acf.Field.prototype.show.apply(this, arguments);
+
+ // check if now visible
+ if( visible ) {
+
+ // show tab
+ this.tab.show();
+
+ // check active tabs
+ this.tabs.refresh();
+ }
+
+ // return
+ return visible;
+ },
+
+ hide: function( lockKey ){
- var $tabs = this.findTabs();
- var $tab = this.findTab();
- var settings = acf.parseArgs($tab.data(), {
- endpoint: false,
- placement: '',
- before: this.$el
- }); // create wrap
+ // hide field and store result
+ var hidden = acf.Field.prototype.hide.apply(this, arguments);
+
+ // check if now hidden
+ if( hidden ) {
+
+ // hide tab
+ this.tab.hide();
+
+ // reset tabs if this was active
+ if( this.isActive() ) {
+ this.tabs.reset();
+ }
+ }
+
+ // return
+ return hidden;
+ },
+
+ enable: function( lockKey ){
- if (!$tabs.length || settings.endpoint) {
- this.tabs = new Tabs(settings);
- } else {
- this.tabs = $tabs.data('acf');
- } // add tab
+ // enable fields
+ this.getFields().map(function( field ){
+ field.enable( CONTEXT );
+ });
+ },
+
+ disable: function( lockKey ){
+
+ // disable fields
+ this.getFields().map(function( field ){
+ field.disable( CONTEXT );
+ });
+ },
-
- this.tab = this.tabs.addTab($tab, this);
- },
- isActive: function () {
- return this.tab.isActive();
- },
- showFields: function () {
- // show fields
- this.getFields().map(function (field) {
- field.show(this.cid, CONTEXT);
- field.hiddenByTab = false;
- }, this);
- },
- hideFields: function () {
- // hide fields
- this.getFields().map(function (field) {
- field.hide(this.cid, CONTEXT);
- field.hiddenByTab = this.tab;
- }, this);
- },
- show: function (lockKey) {
- // show field and store result
- var visible = acf.Field.prototype.show.apply(this, arguments); // check if now visible
-
- if (visible) {
- // show tab
- this.tab.show(); // check active tabs
-
- this.tabs.refresh();
- } // return
-
-
- return visible;
- },
- hide: function (lockKey) {
- // hide field and store result
- var hidden = acf.Field.prototype.hide.apply(this, arguments); // check if now hidden
-
- if (hidden) {
- // hide tab
- this.tab.hide(); // reset tabs if this was active
-
- if (this.isActive()) {
- this.tabs.reset();
- }
- } // return
-
-
- return hidden;
- },
- enable: function (lockKey) {
- // enable fields
- this.getFields().map(function (field) {
- field.enable(CONTEXT);
- });
- },
- disable: function (lockKey) {
- // disable fields
- this.getFields().map(function (field) {
- field.disable(CONTEXT);
- });
- },
- onDuplicate: function (e, $el, $duplicate) {
- if (this.isActive()) {
- $duplicate.prevAll('.acf-tab-wrap:first').remove();
- }
- }
- });
- acf.registerFieldType(Field);
- /**
- * tabs
- *
- * description
- *
- * @date 8/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var i = 0;
- var Tabs = acf.Model.extend({
- tabs: [],
- active: false,
- actions: {
- 'refresh': 'onRefresh'
- },
- data: {
- before: false,
- placement: 'top',
- index: 0,
- initialized: false
- },
- setup: function (settings) {
- // data
- $.extend(this.data, settings); // define this prop to avoid scope issues
-
- this.tabs = [];
- this.active = false; // vars
-
- var placement = this.get('placement');
- var $before = this.get('before');
- var $parent = $before.parent(); // add sidebar for left placement
-
- if (placement == 'left' && $parent.hasClass('acf-fields')) {
- $parent.addClass('-sidebar');
- } // create wrap
-
-
- if ($before.is('tr')) {
- this.$el = $(' ');
- } else {
- this.$el = $('');
- } // append
-
-
- $before.before(this.$el); // set index
-
- this.set('index', i, true);
- i++;
- },
- initializeTabs: function () {
- // find first visible tab
- var tab = this.getVisible().shift(); // remember previous tab state
-
- var order = acf.getPreference('this.tabs') || [];
- var groupIndex = this.get('index');
- var tabIndex = order[groupIndex];
-
- if (this.tabs[tabIndex] && this.tabs[tabIndex].isVisible()) {
- tab = this.tabs[tabIndex];
- } // select
-
-
- if (tab) {
- this.selectTab(tab);
- } else {
- this.closeTabs();
- } // set local variable used by tabsManager
-
-
- this.set('initialized', true);
- },
- getVisible: function () {
- return this.tabs.filter(function (tab) {
- return tab.isVisible();
- });
- },
- getActive: function () {
- return this.active;
- },
- setActive: function (tab) {
- return this.active = tab;
- },
- hasActive: function () {
- return this.active !== false;
- },
- isActive: function (tab) {
- var active = this.getActive();
- return active && active.cid === tab.cid;
- },
- closeActive: function () {
- if (this.hasActive()) {
- this.closeTab(this.getActive());
- }
- },
- openTab: function (tab) {
- // close existing tab
- this.closeActive(); // open
-
- tab.open(); // set active
-
- this.setActive(tab);
- },
- closeTab: function (tab) {
- // close
- tab.close(); // set active
-
- this.setActive(false);
- },
- closeTabs: function () {
- this.tabs.map(this.closeTab, this);
- },
- selectTab: function (tab) {
- // close other tabs
- this.tabs.map(function (t) {
- if (tab.cid !== t.cid) {
- this.closeTab(t);
- }
- }, this); // open
-
- this.openTab(tab);
- },
- addTab: function ($a, field) {
- // create
- var $li = $(' ' + $a.outerHTML() + ' '); // append
-
- this.$('ul').append($li); // initialize
-
- var tab = new Tab({
- $el: $li,
- field: field,
- group: this
- }); // store
-
- this.tabs.push(tab); // return
-
- return tab;
- },
- reset: function () {
- // close existing tab
- this.closeActive(); // find and active a tab
-
- return this.refresh();
- },
- refresh: function () {
- // bail early if active already exists
- if (this.hasActive()) {
- return false;
- } // find next active tab
-
-
- var tab = this.getVisible().shift(); // open tab
-
- if (tab) {
- this.openTab(tab);
- } // return
-
-
- return tab;
- },
- onRefresh: function () {
- // only for left placements
- if (this.get('placement') !== 'left') {
- return;
- } // vars
-
-
- var $parent = this.$el.parent();
- var $list = this.$el.children('ul');
- var attribute = $parent.is('td') ? 'height' : 'min-height'; // find height (minus 1 for border-bottom)
-
- var height = $list.position().top + $list.outerHeight(true) - 1; // add css
-
- $parent.css(attribute, height);
- }
- });
- var Tab = acf.Model.extend({
- group: false,
- field: false,
- events: {
- 'click a': 'onClick'
- },
- index: function () {
- return this.$el.index();
- },
- isVisible: function () {
- return acf.isVisible(this.$el);
- },
- isActive: function () {
- return this.$el.hasClass('active');
- },
- open: function () {
- // add class
- this.$el.addClass('active'); // show field
-
- this.field.showFields();
- },
- close: function () {
- // remove class
- this.$el.removeClass('active'); // hide field
-
- this.field.hideFields();
- },
- onClick: function (e, $el) {
- // prevent default
- e.preventDefault(); // toggle
-
- this.toggle();
- },
- toggle: function () {
- // bail early if already active
- if (this.isActive()) {
- return;
- } // toggle this tab
-
-
- this.group.openTab(this);
- }
- });
- var tabsManager = new acf.Model({
- priority: 50,
- actions: {
- 'prepare': 'render',
- 'append': 'render',
- 'unload': 'onUnload',
- 'invalid_field': 'onInvalidField'
- },
- findTabs: function () {
- return $('.acf-tab-wrap');
- },
- getTabs: function () {
- return acf.getInstances(this.findTabs());
- },
- render: function ($el) {
- this.getTabs().map(function (tabs) {
- if (!tabs.get('initialized')) {
- tabs.initializeTabs();
- }
- });
- },
- onInvalidField: function (field) {
- // bail early if busy
- if (this.busy) {
- return;
- } // ignore if not hidden by tab
-
-
- if (!field.hiddenByTab) {
- return;
- } // toggle tab
-
-
- field.hiddenByTab.toggle(); // ignore other invalid fields
-
- this.busy = true;
- this.setTimeout(function () {
- this.busy = false;
- }, 100);
- },
- onUnload: function () {
- // vars
- var order = []; // loop
-
- this.getTabs().map(function (group) {
- var active = group.hasActive() ? group.getActive().index() : 0;
- order.push(active);
- }); // bail if no tabs
-
- if (!order.length) {
- return;
- } // update
-
-
- acf.setPreference('this.tabs', order);
- }
- });
+ onDuplicate: function( e, $el, $duplicate ){
+ if( this.isActive() ) {
+ $duplicate.prevAll('.acf-tab-wrap:first').remove();
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
+
+
+ /**
+ * tabs
+ *
+ * description
+ *
+ * @date 8/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var i = 0;
+ var Tabs = acf.Model.extend({
+
+ tabs: [],
+
+ active: false,
+
+ actions: {
+ 'refresh': 'onRefresh'
+ },
+
+ data: {
+ before: false,
+ placement: 'top',
+ index: 0,
+ initialized: false,
+ },
+
+ setup: function( settings ){
+
+ // data
+ $.extend(this.data, settings);
+
+ // define this prop to avoid scope issues
+ this.tabs = [];
+ this.active = false;
+
+ // vars
+ var placement = this.get('placement');
+ var $before = this.get('before');
+ var $parent = $before.parent();
+
+ // add sidebar for left placement
+ if( placement == 'left' && $parent.hasClass('acf-fields') ) {
+ $parent.addClass('-sidebar');
+ }
+
+ // create wrap
+ if( $before.is('tr') ) {
+ this.$el = $(' ');
+ } else {
+ this.$el = $('');
+ }
+
+ // append
+ $before.before( this.$el );
+
+ // set index
+ this.set('index', i, true);
+ i++;
+ },
+
+ initializeTabs: function(){
+
+ // find first visible tab
+ var tab = this.getVisible().shift();
+
+ // remember previous tab state
+ var order = acf.getPreference('this.tabs') || [];
+ var groupIndex = this.get('index');
+ var tabIndex = order[ groupIndex ];
+
+ if( this.tabs[ tabIndex ] && this.tabs[ tabIndex ].isVisible() ) {
+ tab = this.tabs[ tabIndex ];
+ }
+
+ // select
+ if( tab ) {
+ this.selectTab( tab );
+ } else {
+ this.closeTabs();
+ }
+
+ // set local variable used by tabsManager
+ this.set('initialized', true);
+ },
+
+ getVisible: function(){
+ return this.tabs.filter(function( tab ){
+ return tab.isVisible();
+ });
+ },
+
+ getActive: function(){
+ return this.active;
+ },
+
+ setActive: function( tab ){
+ return this.active = tab;
+ },
+
+ hasActive: function(){
+ return (this.active !== false);
+ },
+
+ isActive: function( tab ){
+ var active = this.getActive();
+ return (active && active.cid === tab.cid);
+ },
+
+ closeActive: function(){
+ if( this.hasActive() ) {
+ this.closeTab( this.getActive() );
+ }
+ },
+
+ openTab: function( tab ){
+
+ // close existing tab
+ this.closeActive();
+
+ // open
+ tab.open();
+
+ // set active
+ this.setActive( tab );
+ },
+
+ closeTab: function( tab ){
+
+ // close
+ tab.close();
+
+ // set active
+ this.setActive( false );
+ },
+
+ closeTabs: function(){
+ this.tabs.map( this.closeTab, this );
+ },
+
+ selectTab: function( tab ){
+
+ // close other tabs
+ this.tabs.map(function( t ){
+ if( tab.cid !== t.cid ) {
+ this.closeTab( t );
+ }
+ }, this);
+
+ // open
+ this.openTab( tab );
+
+ },
+
+ addTab: function( $a, field ){
+
+ // create
+ var $li = $(' ' + $a.outerHTML() + ' ');
+
+ // append
+ this.$('ul').append( $li );
+
+ // initialize
+ var tab = new Tab({
+ $el: $li,
+ field: field,
+ group: this,
+ });
+
+ // store
+ this.tabs.push( tab );
+
+ // return
+ return tab;
+ },
+
+ reset: function(){
+
+ // close existing tab
+ this.closeActive();
+
+ // find and active a tab
+ return this.refresh();
+ },
+
+ refresh: function(){
+
+ // bail early if active already exists
+ if( this.hasActive() ) {
+ return false;
+ }
+
+ // find next active tab
+ var tab = this.getVisible().shift();
+
+ // open tab
+ if( tab ) {
+ this.openTab( tab );
+ }
+
+ // return
+ return tab;
+ },
+
+ onRefresh: function(){
+
+ // only for left placements
+ if( this.get('placement') !== 'left' ) {
+ return;
+ }
+
+ // vars
+ var $parent = this.$el.parent();
+ var $list = this.$el.children('ul');
+ var attribute = $parent.is('td') ? 'height' : 'min-height';
+
+ // find height (minus 1 for border-bottom)
+ var height = $list.position().top + $list.outerHeight(true) - 1;
+
+ // add css
+ $parent.css(attribute, height);
+ }
+ });
+
+ var Tab = acf.Model.extend({
+
+ group: false,
+
+ field: false,
+
+ events: {
+ 'click a': 'onClick'
+ },
+
+ index: function(){
+ return this.$el.index();
+ },
+
+ isVisible: function(){
+ return acf.isVisible( this.$el );
+ },
+
+ isActive: function(){
+ return this.$el.hasClass('active');
+ },
+
+ open: function(){
+
+ // add class
+ this.$el.addClass('active');
+
+ // show field
+ this.field.showFields();
+ },
+
+ close: function(){
+
+ // remove class
+ this.$el.removeClass('active');
+
+ // hide field
+ this.field.hideFields();
+ },
+
+ onClick: function( e, $el ){
+
+ // prevent default
+ e.preventDefault();
+
+ // toggle
+ this.toggle();
+ },
+
+ toggle: function(){
+
+ // bail early if already active
+ if( this.isActive() ) {
+ return;
+ }
+
+ // toggle this tab
+ this.group.openTab( this );
+ }
+ });
+
+ var tabsManager = new acf.Model({
+
+ priority: 50,
+
+ actions: {
+ 'prepare': 'render',
+ 'append': 'render',
+ 'unload': 'onUnload',
+ 'invalid_field': 'onInvalidField'
+ },
+
+ findTabs: function(){
+ return $('.acf-tab-wrap');
+ },
+
+ getTabs: function(){
+ return acf.getInstances( this.findTabs() );
+ },
+
+ render: function( $el ){
+ this.getTabs().map(function( tabs ){
+ if( !tabs.get('initialized') ) {
+ tabs.initializeTabs();
+ }
+ });
+ },
+
+ onInvalidField: function( field ){
+
+ // bail early if busy
+ if( this.busy ) {
+ return;
+ }
+
+ // ignore if not hidden by tab
+ if( !field.hiddenByTab ) {
+ return;
+ }
+
+ // toggle tab
+ field.hiddenByTab.toggle();
+
+ // ignore other invalid fields
+ this.busy = true;
+ this.setTimeout(function(){
+ this.busy = false;
+ }, 100);
+ },
+
+ onUnload: function(){
+
+ // vars
+ var order = [];
+
+ // loop
+ this.getTabs().map(function( group ){
+ var active = group.hasActive() ? group.getActive().index() : 0;
+ order.push(active);
+ });
+
+ // bail if no tabs
+ if( !order.length ) {
+ return;
+ }
+
+ // update
+ acf.setPreference('this.tabs', order);
+ }
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.models.SelectField.extend({
- type: 'post_object'
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.models.SelectField.extend({
+ type: 'post_object',
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.models.SelectField.extend({
- type: 'page_link'
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.models.SelectField.extend({
+ type: 'page_link',
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.models.SelectField.extend({
- type: 'user'
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.models.SelectField.extend({
+ type: 'user',
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'taxonomy',
+
+ data: {
+ 'ftype': 'select'
+ },
+
+ select2: false,
+
+ wait: 'load',
+
+ events: {
+ 'click a[data-name="add"]': 'onClickAdd',
+ 'click input[type="radio"]': 'onClickRadio',
+ 'removeField': 'onRemove'
+ },
+
+ $control: function(){
+ return this.$('.acf-taxonomy-field');
+ },
+
+ $input: function(){
+ return this.getRelatedPrototype().$input.apply(this, arguments);
+ },
+
+ getRelatedType: function(){
+
+ // vars
+ var fieldType = this.get('ftype');
+
+ // normalize
+ if( fieldType == 'multi_select' ) {
+ fieldType = 'select';
+ }
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'taxonomy',
- data: {
- 'ftype': 'select'
- },
- select2: false,
- wait: 'load',
- events: {
- 'click a[data-name="add"]': 'onClickAdd',
- 'click input[type="radio"]': 'onClickRadio',
- 'removeField': 'onRemove'
- },
- $control: function () {
- return this.$('.acf-taxonomy-field');
- },
- $input: function () {
- return this.getRelatedPrototype().$input.apply(this, arguments);
- },
- getRelatedType: function () {
- // vars
- var fieldType = this.get('ftype'); // normalize
-
- if (fieldType == 'multi_select') {
- fieldType = 'select';
- } // return
-
-
- return fieldType;
- },
- getRelatedPrototype: function () {
- return acf.getFieldType(this.getRelatedType()).prototype;
- },
- getValue: function () {
- return this.getRelatedPrototype().getValue.apply(this, arguments);
- },
- setValue: function () {
- return this.getRelatedPrototype().setValue.apply(this, arguments);
- },
- initialize: function () {
- this.getRelatedPrototype().initialize.apply(this, arguments);
- },
- onRemove: function () {
- var proto = this.getRelatedPrototype();
-
- if (proto.onRemove) {
- proto.onRemove.apply(this, arguments);
- }
- },
- onClickAdd: function (e, $el) {
- // vars
- var field = this;
- var popup = false;
- var $form = false;
- var $name = false;
- var $parent = false;
- var $button = false;
- var $message = false;
- var notice = false; // step 1.
-
- var step1 = function () {
- // popup
- popup = acf.newPopup({
- title: $el.attr('title'),
- loading: true,
- width: '300px'
- }); // ajax
-
- var ajaxData = {
- action: 'acf/fields/taxonomy/add_term',
- field_key: field.get('key')
- }; // get HTML
-
- $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'html',
- success: step2
- });
- }; // step 2.
-
-
- var step2 = function (html) {
- // update popup
- popup.loading(false);
- popup.content(html); // vars
-
- $form = popup.$('form');
- $name = popup.$('input[name="term_name"]');
- $parent = popup.$('select[name="term_parent"]');
- $button = popup.$('.acf-submit-button'); // focus
-
- $name.trigger('focus'); // submit form
-
- popup.on('submit', 'form', step3);
- }; // step 3.
-
-
- var step3 = function (e, $el) {
- // prevent
- e.preventDefault();
- e.stopImmediatePropagation(); // basic validation
-
- if ($name.val() === '') {
- $name.trigger('focus');
- return false;
- } // disable
-
-
- acf.startButtonLoading($button); // ajax
-
- var ajaxData = {
- action: 'acf/fields/taxonomy/add_term',
- field_key: field.get('key'),
- term_name: $name.val(),
- term_parent: $parent.length ? $parent.val() : 0
- };
- $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'json',
- success: step4
- });
- }; // step 4.
-
-
- var step4 = function (json) {
- // enable
- acf.stopButtonLoading($button); // remove prev notice
-
- if (notice) {
- notice.remove();
- } // success
-
-
- if (acf.isAjaxSuccess(json)) {
- // clear name
- $name.val(''); // update term lists
-
- step5(json.data); // notice
-
- notice = acf.newNotice({
- type: 'success',
- text: acf.getAjaxMessage(json),
- target: $form,
- timeout: 2000,
- dismiss: false
- });
- } else {
- // notice
- notice = acf.newNotice({
- type: 'error',
- text: acf.getAjaxError(json),
- target: $form,
- timeout: 2000,
- dismiss: false
- });
- } // focus
-
-
- $name.trigger('focus');
- }; // step 5.
-
-
- var step5 = function (term) {
- // update parent dropdown
- var $option = $('' + term.term_label + ' ');
-
- if (term.term_parent) {
- $parent.children('option[value="' + term.term_parent + '"]').after($option);
- } else {
- $parent.append($option);
- } // add this new term to all taxonomy field
-
-
- var fields = acf.getFields({
- type: 'taxonomy'
- });
- fields.map(function (otherField) {
- if (otherField.get('taxonomy') == field.get('taxonomy')) {
- otherField.appendTerm(term);
- }
- }); // select
-
- field.selectTerm(term.term_id);
- }; // run
-
-
- step1();
- },
- appendTerm: function (term) {
- if (this.getRelatedType() == 'select') {
- this.appendTermSelect(term);
- } else {
- this.appendTermCheckbox(term);
- }
- },
- appendTermSelect: function (term) {
- this.select2.addOption({
- id: term.term_id,
- text: term.term_label
- });
- },
- appendTermCheckbox: function (term) {
- // vars
- var name = this.$('[name]:first').attr('name');
- var $ul = this.$('ul:first'); // allow multiple selection
-
- if (this.getRelatedType() == 'checkbox') {
- name += '[]';
- } // create new li
-
-
- var $li = $(['', '', ' ', '' + term.term_name + ' ', ' ', ' '].join('')); // find parent
-
- if (term.term_parent) {
- // vars
- var $parent = $ul.find('li[data-id="' + term.term_parent + '"]'); // update vars
-
- $ul = $parent.children('ul'); // create ul
-
- if (!$ul.exists()) {
- $ul = $('');
- $parent.append($ul);
- }
- } // append
-
-
- $ul.append($li);
- },
- selectTerm: function (id) {
- if (this.getRelatedType() == 'select') {
- this.select2.selectOption(id);
- } else {
- var $input = this.$('input[value="' + id + '"]');
- $input.prop('checked', true).trigger('change');
- }
- },
- onClickRadio: function (e, $el) {
- // vars
- var $label = $el.parent('label');
- var selected = $label.hasClass('selected'); // remove previous selected
-
- this.$('.selected').removeClass('selected'); // add active class
-
- $label.addClass('selected'); // allow null
-
- if (this.get('allow_null') && selected) {
- $label.removeClass('selected');
- $el.prop('checked', false).trigger('change');
- }
- }
- });
- acf.registerFieldType(Field);
+ // return
+ return fieldType;
+
+ },
+
+ getRelatedPrototype: function(){
+ return acf.getFieldType( this.getRelatedType() ).prototype;
+ },
+
+ getValue: function(){
+ return this.getRelatedPrototype().getValue.apply(this, arguments);
+ },
+
+ setValue: function(){
+ return this.getRelatedPrototype().setValue.apply(this, arguments);
+ },
+
+ initialize: function(){
+ this.getRelatedPrototype().initialize.apply(this, arguments);
+ },
+
+ onRemove: function(){
+ var proto = this.getRelatedPrototype();
+ if( proto.onRemove ) {
+ proto.onRemove.apply(this, arguments);
+ }
+ },
+
+ onClickAdd: function( e, $el ){
+
+ // vars
+ var field = this;
+ var popup = false;
+ var $form = false;
+ var $name = false;
+ var $parent = false;
+ var $button = false;
+ var $message = false;
+ var notice = false;
+
+ // step 1.
+ var step1 = function(){
+
+ // popup
+ popup = acf.newPopup({
+ title: $el.attr('title'),
+ loading: true,
+ width: '300px'
+ });
+
+ // ajax
+ var ajaxData = {
+ action: 'acf/fields/taxonomy/add_term',
+ field_key: field.get('key')
+ };
+
+ // get HTML
+ $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxData),
+ type: 'post',
+ dataType: 'html',
+ success: step2
+ });
+ };
+
+ // step 2.
+ var step2 = function( html ){
+
+ // update popup
+ popup.loading(false);
+ popup.content(html);
+
+ // vars
+ $form = popup.$('form');
+ $name = popup.$('input[name="term_name"]');
+ $parent = popup.$('select[name="term_parent"]');
+ $button = popup.$('.acf-submit-button');
+
+ // focus
+ $name.trigger('focus');
+
+ // submit form
+ popup.on('submit', 'form', step3);
+ };
+
+ // step 3.
+ var step3 = function( e, $el ){
+
+ // prevent
+ e.preventDefault();
+ e.stopImmediatePropagation();
+
+ // basic validation
+ if( $name.val() === '' ) {
+ $name.trigger('focus');
+ return false;
+ }
+
+ // disable
+ acf.startButtonLoading( $button );
+
+ // ajax
+ var ajaxData = {
+ action: 'acf/fields/taxonomy/add_term',
+ field_key: field.get('key'),
+ term_name: $name.val(),
+ term_parent: $parent.length ? $parent.val() : 0
+ };
+
+ $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(ajaxData),
+ type: 'post',
+ dataType: 'json',
+ success: step4
+ });
+ };
+
+ // step 4.
+ var step4 = function( json ){
+
+ // enable
+ acf.stopButtonLoading( $button );
+
+ // remove prev notice
+ if( notice ) {
+ notice.remove();
+ }
+
+ // success
+ if( acf.isAjaxSuccess(json) ) {
+
+ // clear name
+ $name.val('');
+
+ // update term lists
+ step5( json.data );
+
+ // notice
+ notice = acf.newNotice({
+ type: 'success',
+ text: acf.getAjaxMessage(json),
+ target: $form,
+ timeout: 2000,
+ dismiss: false
+ });
+
+ } else {
+
+ // notice
+ notice = acf.newNotice({
+ type: 'error',
+ text: acf.getAjaxError(json),
+ target: $form,
+ timeout: 2000,
+ dismiss: false
+ });
+ }
+
+ // focus
+ $name.trigger('focus');
+ };
+
+ // step 5.
+ var step5 = function( term ){
+
+ // update parent dropdown
+ var $option = $('' + term.term_label + ' ');
+ if( term.term_parent ) {
+ $parent.children('option[value="' + term.term_parent + '"]').after( $option );
+ } else {
+ $parent.append( $option );
+ }
+
+ // add this new term to all taxonomy field
+ var fields = acf.getFields({
+ type: 'taxonomy'
+ });
+
+ fields.map(function( otherField ){
+ if( otherField.get('taxonomy') == field.get('taxonomy') ) {
+ otherField.appendTerm( term );
+ }
+ });
+
+ // select
+ field.selectTerm( term.term_id );
+ };
+
+ // run
+ step1();
+ },
+
+ appendTerm: function( term ){
+
+ if( this.getRelatedType() == 'select' ) {
+ this.appendTermSelect( term );
+ } else {
+ this.appendTermCheckbox( term );
+ }
+ },
+
+ appendTermSelect: function( term ){
+
+ this.select2.addOption({
+ id: term.term_id,
+ text: term.term_label
+ });
+
+ },
+
+ appendTermCheckbox: function( term ){
+
+ // vars
+ var name = this.$('[name]:first').attr('name');
+ var $ul = this.$('ul:first');
+
+ // allow multiple selection
+ if( this.getRelatedType() == 'checkbox' ) {
+ name += '[]';
+ }
+
+ // create new li
+ var $li = $([
+ '',
+ '',
+ ' ',
+ '' + term.term_name + ' ',
+ ' ',
+ ' '
+ ].join(''));
+
+ // find parent
+ if( term.term_parent ) {
+
+ // vars
+ var $parent = $ul.find('li[data-id="' + term.term_parent + '"]');
+
+ // update vars
+ $ul = $parent.children('ul');
+
+ // create ul
+ if( !$ul.exists() ) {
+ $ul = $('');
+ $parent.append( $ul );
+ }
+ }
+
+ // append
+ $ul.append( $li );
+ },
+
+ selectTerm: function( id ){
+ if( this.getRelatedType() == 'select' ) {
+ this.select2.selectOption( id );
+ } else {
+ var $input = this.$('input[value="' + id + '"]');
+ $input.prop('checked', true).trigger('change');
+ }
+ },
+
+ onClickRadio: function( e, $el ){
+
+ // vars
+ var $label = $el.parent('label');
+ var selected = $label.hasClass('selected');
+
+ // remove previous selected
+ this.$('.selected').removeClass('selected');
+
+ // add active class
+ $label.addClass('selected');
+
+ // allow null
+ if( this.get('allow_null') && selected ) {
+ $label.removeClass('selected');
+ $el.prop('checked', false).trigger('change');
+ }
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.models.DatePickerField.extend({
+
+ type: 'time_picker',
+
+ $control: function(){
+ return this.$('.acf-time-picker');
+ },
+
+ initialize: function(){
+
+ // vars
+ var $input = this.$input();
+ var $inputText = this.$inputText();
+
+ // args
+ var args = {
+ timeFormat: this.get('time_format'),
+ altField: $input,
+ altFieldTimeOnly: false,
+ altTimeFormat: 'HH:mm:ss',
+ showButtonPanel: true,
+ controlType: 'select',
+ oneLine: true,
+ closeText: acf.get('dateTimePickerL10n').selectText,
+ timeOnly: true,
+ };
+
+ // add custom 'Close = Select' functionality
+ args.onClose = function( value, dp_instance, t_instance ){
+
+ // vars
+ var $close = dp_instance.dpDiv.find('.ui-datepicker-close');
+
+ // if clicking close button
+ if( !value && $close.is(':hover') ) {
+ t_instance._updateDateTime();
+ }
+ };
-(function ($, undefined) {
- var Field = acf.models.DatePickerField.extend({
- type: 'time_picker',
- $control: function () {
- return this.$('.acf-time-picker');
- },
- initialize: function () {
- // vars
- var $input = this.$input();
- var $inputText = this.$inputText(); // args
-
- var args = {
- timeFormat: this.get('time_format'),
- altField: $input,
- altFieldTimeOnly: false,
- altTimeFormat: 'HH:mm:ss',
- showButtonPanel: true,
- controlType: 'select',
- oneLine: true,
- closeText: acf.get('dateTimePickerL10n').selectText,
- timeOnly: true
- }; // add custom 'Close = Select' functionality
-
- args.onClose = function (value, dp_instance, t_instance) {
- // vars
- var $close = dp_instance.dpDiv.find('.ui-datepicker-close'); // if clicking close button
-
- if (!value && $close.is(':hover')) {
- t_instance._updateDateTime();
- }
- }; // filter
-
-
- args = acf.applyFilters('time_picker_args', args, this); // add date time picker
-
- acf.newTimePicker($inputText, args); // action
-
- acf.doAction('time_picker_init', $inputText, args, this);
- }
- });
- acf.registerFieldType(Field); // add
-
- acf.newTimePicker = function ($input, args) {
- // bail ealry if no datepicker library
- if (typeof $.timepicker === 'undefined') {
- return false;
- } // defaults
-
-
- args = args || {}; // initialize
-
- $input.timepicker(args); // wrap the datepicker (only if it hasn't already been wrapped)
-
- if ($('body > #ui-datepicker-div').exists()) {
- $('body > #ui-datepicker-div').wrap('
');
- }
- };
+
+ // filter
+ args = acf.applyFilters('time_picker_args', args, this);
+
+ // add date time picker
+ acf.newTimePicker( $inputText, args );
+
+ // action
+ acf.doAction('time_picker_init', $inputText, args, this);
+ }
+ });
+
+ acf.registerFieldType( Field );
+
+
+ // add
+ acf.newTimePicker = function( $input, args ){
+
+ // bail ealry if no datepicker library
+ if( typeof $.timepicker === 'undefined' ) {
+ return false;
+ }
+
+ // defaults
+ args = args || {};
+
+ // initialize
+ $input.timepicker( args );
+
+ // wrap the datepicker (only if it hasn't already been wrapped)
+ if( $('body > #ui-datepicker-div').exists() ) {
+ $('body > #ui-datepicker-div').wrap('
');
+ }
+ };
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'true_false',
- events: {
- 'change .acf-switch-input': 'onChange',
- 'focus .acf-switch-input': 'onFocus',
- 'blur .acf-switch-input': 'onBlur',
- 'keypress .acf-switch-input': 'onKeypress'
- },
- $input: function () {
- return this.$('input[type="checkbox"]');
- },
- $switch: function () {
- return this.$('.acf-switch');
- },
- getValue: function () {
- return this.$input().prop('checked') ? 1 : 0;
- },
- initialize: function () {
- this.render();
- },
- render: function () {
- // vars
- var $switch = this.$switch(); // bail ealry if no $switch
-
- if (!$switch.length) return; // vars
-
- var $on = $switch.children('.acf-switch-on');
- var $off = $switch.children('.acf-switch-off');
- var width = Math.max($on.width(), $off.width()); // bail ealry if no width
-
- if (!width) return; // set widths
-
- $on.css('min-width', width);
- $off.css('min-width', width);
- },
- switchOn: function () {
- this.$input().prop('checked', true);
- this.$switch().addClass('-on');
- },
- switchOff: function () {
- this.$input().prop('checked', false);
- this.$switch().removeClass('-on');
- },
- onChange: function (e, $el) {
- if ($el.prop('checked')) {
- this.switchOn();
- } else {
- this.switchOff();
- }
- },
- onFocus: function (e, $el) {
- this.$switch().addClass('-focus');
- },
- onBlur: function (e, $el) {
- this.$switch().removeClass('-focus');
- },
- onKeypress: function (e, $el) {
- // left
- if (e.keyCode === 37) {
- return this.switchOff();
- } // right
-
-
- if (e.keyCode === 39) {
- return this.switchOn();
- }
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'true_false',
+
+ events: {
+ 'change .acf-switch-input': 'onChange',
+ 'focus .acf-switch-input': 'onFocus',
+ 'blur .acf-switch-input': 'onBlur',
+ 'keypress .acf-switch-input': 'onKeypress'
+ },
+
+ $input: function(){
+ return this.$('input[type="checkbox"]');
+ },
+
+ $switch: function(){
+ return this.$('.acf-switch');
+ },
+
+ getValue: function(){
+ return this.$input().prop('checked') ? 1 : 0;
+ },
+
+ initialize: function(){
+ this.render();
+ },
+
+ render: function(){
+
+ // vars
+ var $switch = this.$switch();
+
+ // bail ealry if no $switch
+ if( !$switch.length ) return;
+
+ // vars
+ var $on = $switch.children('.acf-switch-on');
+ var $off = $switch.children('.acf-switch-off');
+ var width = Math.max( $on.width(), $off.width() );
+
+ // bail ealry if no width
+ if( !width ) return;
+
+ // set widths
+ $on.css( 'min-width', width );
+ $off.css( 'min-width', width );
+
+ },
+
+ switchOn: function() {
+ this.$input().prop('checked', true);
+ this.$switch().addClass('-on');
+ },
+
+ switchOff: function() {
+ this.$input().prop('checked', false);
+ this.$switch().removeClass('-on');
+ },
+
+ onChange: function( e, $el ){
+ if( $el.prop('checked') ) {
+ this.switchOn();
+ } else {
+ this.switchOff();
+ }
+ },
+
+ onFocus: function( e, $el ){
+ this.$switch().addClass('-focus');
+ },
+
+ onBlur: function( e, $el ){
+ this.$switch().removeClass('-focus');
+ },
+
+ onKeypress: function( e, $el ){
+
+ // left
+ if( e.keyCode === 37 ) {
+ return this.switchOff();
+ }
+
+ // right
+ if( e.keyCode === 39 ) {
+ return this.switchOn();
+ }
+
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
-
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'url',
- events: {
- 'keyup input[type="url"]': 'onkeyup'
- },
- $control: function () {
- return this.$('.acf-input-wrap');
- },
- $input: function () {
- return this.$('input[type="url"]');
- },
- initialize: function () {
- this.render();
- },
- isValid: function () {
- // vars
- var val = this.val(); // bail early if no val
-
- if (!val) {
- return false;
- } // url
-
-
- if (val.indexOf('://') !== -1) {
- return true;
- } // protocol relative url
-
-
- if (val.indexOf('//') === 0) {
- return true;
- } // return
-
-
- return false;
- },
- render: function () {
- // add class
- if (this.isValid()) {
- this.$control().addClass('-valid');
- } else {
- this.$control().removeClass('-valid');
- }
- },
- onkeyup: function (e, $el) {
- this.render();
- }
- });
- acf.registerFieldType(Field);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'url',
+
+ events: {
+ 'keyup input[type="url"]': 'onkeyup'
+ },
+
+ $control: function(){
+ return this.$('.acf-input-wrap');
+ },
+
+ $input: function(){
+ return this.$('input[type="url"]');
+ },
+
+ initialize: function(){
+ this.render();
+ },
+
+ isValid: function(){
+
+ // vars
+ var val = this.val();
+
+ // bail early if no val
+ if( !val ) {
+ return false;
+ }
+
+ // url
+ if( val.indexOf('://') !== -1 ) {
+ return true;
+ }
+
+ // protocol relative url
+ if( val.indexOf('//') === 0 ) {
+ return true;
+ }
+
+ // return
+ return false;
+ },
+
+ render: function(){
+
+ // add class
+ if( this.isValid() ) {
+ this.$control().addClass('-valid');
+ } else {
+ this.$control().removeClass('-valid');
+ }
+ },
+
+ onkeyup: function( e, $el ){
+ this.render();
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ var Field = acf.Field.extend({
+
+ type: 'wysiwyg',
+
+ wait: 'load',
+
+ events: {
+ 'mousedown .acf-editor-wrap.delay': 'onMousedown',
+ 'unmountField': 'disableEditor',
+ 'remountField': 'enableEditor',
+ 'removeField': 'disableEditor'
+ },
+
+ $control: function(){
+ return this.$('.acf-editor-wrap');
+ },
+
+ $input: function(){
+ return this.$('textarea');
+ },
+
+ getMode: function(){
+ return this.$control().hasClass('tmce-active') ? 'visual' : 'text';
+ },
+
+ initialize: function(){
+
+ // initializeEditor if no delay
+ if( !this.$control().hasClass('delay') ) {
+ this.initializeEditor();
+ }
+ },
+
+ initializeEditor: function(){
+
+ // vars
+ var $wrap = this.$control();
+ var $textarea = this.$input();
+ var args = {
+ tinymce: true,
+ quicktags: true,
+ toolbar: this.get('toolbar'),
+ mode: this.getMode(),
+ field: this
+ };
+
+ // generate new id
+ var oldId = $textarea.attr('id');
+ var newId = acf.uniqueId('acf-editor-');
+
+ // Backup textarea data.
+ var inputData = $textarea.data();
+ var inputVal = $textarea.val();
+
+ // rename
+ acf.rename({
+ target: $wrap,
+ search: oldId,
+ replace: newId,
+ destructive: true
+ });
+
+ // update id
+ this.set('id', newId, true);
+
+ // apply data to new textarea (acf.rename creates a new textarea element due to destructive mode)
+ // fixes bug where conditional logic "disabled" is lost during "screen_check"
+ this.$input().data( inputData ).val( inputVal );
-(function ($, undefined) {
- var Field = acf.Field.extend({
- type: 'wysiwyg',
- wait: 'load',
- events: {
- 'mousedown .acf-editor-wrap.delay': 'onMousedown',
- 'unmountField': 'disableEditor',
- 'remountField': 'enableEditor',
- 'removeField': 'disableEditor'
- },
- $control: function () {
- return this.$('.acf-editor-wrap');
- },
- $input: function () {
- return this.$('textarea');
- },
- getMode: function () {
- return this.$control().hasClass('tmce-active') ? 'visual' : 'text';
- },
- initialize: function () {
- // initializeEditor if no delay
- if (!this.$control().hasClass('delay')) {
- this.initializeEditor();
- }
- },
- initializeEditor: function () {
- // vars
- var $wrap = this.$control();
- var $textarea = this.$input();
- var args = {
- tinymce: true,
- quicktags: true,
- toolbar: this.get('toolbar'),
- mode: this.getMode(),
- field: this
- }; // generate new id
-
- var oldId = $textarea.attr('id');
- var newId = acf.uniqueId('acf-editor-'); // Backup textarea data.
-
- var inputData = $textarea.data();
- var inputVal = $textarea.val(); // rename
-
- acf.rename({
- target: $wrap,
- search: oldId,
- replace: newId,
- destructive: true
- }); // update id
-
- this.set('id', newId, true); // apply data to new textarea (acf.rename creates a new textarea element due to destructive mode)
- // fixes bug where conditional logic "disabled" is lost during "screen_check"
-
- this.$input().data(inputData).val(inputVal); // initialize
-
- acf.tinymce.initialize(newId, args);
- },
- onMousedown: function (e) {
- // prevent default
- e.preventDefault(); // remove delay class
-
- var $wrap = this.$control();
- $wrap.removeClass('delay');
- $wrap.find('.acf-editor-toolbar').remove(); // initialize
-
- this.initializeEditor();
- },
- enableEditor: function () {
- if (this.getMode() == 'visual') {
- acf.tinymce.enable(this.get('id'));
- }
- },
- disableEditor: function () {
- acf.tinymce.destroy(this.get('id'));
- }
- });
- acf.registerFieldType(Field);
+ // initialize
+ acf.tinymce.initialize( newId, args );
+ },
+
+ onMousedown: function( e ){
+
+ // prevent default
+ e.preventDefault();
+
+ // remove delay class
+ var $wrap = this.$control();
+ $wrap.removeClass('delay');
+ $wrap.find('.acf-editor-toolbar').remove();
+
+ // initialize
+ this.initializeEditor();
+ },
+
+ enableEditor: function(){
+ if( this.getMode() == 'visual' ) {
+ acf.tinymce.enable( this.get('id') );
+ }
+ },
+
+ disableEditor: function(){
+ acf.tinymce.destroy( this.get('id') );
+ }
+ });
+
+ acf.registerFieldType( Field );
+
})(jQuery);
+(function($, undefined){
+
+ // vars
+ var storage = [];
+
+ /**
+ * acf.Condition
+ *
+ * description
+ *
+ * @date 23/3/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.Condition = acf.Model.extend({
+
+ type: '', // used for model name
+ operator: '==', // rule operator
+ label: '', // label shown when editing fields
+ choiceType: 'input', // input, select
+ fieldTypes: [], // auto connect this conditions with these field types
+
+ data: {
+ conditions: false, // the parent instance
+ field: false, // the field which we query against
+ rule: {} // the rule [field, operator, value]
+ },
+
+ events: {
+ 'change': 'change',
+ 'keyup': 'change',
+ 'enableField': 'change',
+ 'disableField': 'change'
+ },
+
+ setup: function( props ){
+ $.extend(this.data, props);
+ },
+
+ getEventTarget: function( $el, event ){
+ return $el || this.get('field').$el;
+ },
+
+ change: function( e, $el ){
+ this.get('conditions').change( e );
+ },
+
+ match: function( rule, field ){
+ return false;
+ },
+
+ calculate: function(){
+ return this.match( this.get('rule'), this.get('field') );
+ },
+
+ choices: function( field ){
+ return ' ';
+ }
+ });
+
+ /**
+ * acf.newCondition
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.newCondition = function( rule, conditions ){
+
+ // currently setting up conditions for fieldX, this field is the 'target'
+ var target = conditions.get('field');
+
+ // use the 'target' to find the 'trigger' field.
+ // - this field is used to setup the conditional logic events
+ var field = target.getField( rule.field );
+
+ // bail ealry if no target or no field (possible if field doesn't exist due to HTML error)
+ if( !target || !field ) {
+ return false;
+ }
+
+ // vars
+ var args = {
+ rule: rule,
+ target: target,
+ conditions: conditions,
+ field: field
+ };
+
+ // vars
+ var fieldType = field.get('type');
+ var operator = rule.operator;
+
+ // get avaibale conditions
+ var conditionTypes = acf.getConditionTypes({
+ fieldType: fieldType,
+ operator: operator,
+ });
+
+ // instantiate
+ var model = conditionTypes[0] || acf.Condition;
+
+ // instantiate
+ var condition = new model( args );
+
+ // return
+ return condition;
+ };
-(function ($, undefined) {
- // vars
- var storage = [];
- /**
- * acf.Condition
- *
- * description
- *
- * @date 23/3/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.Condition = acf.Model.extend({
- type: '',
- // used for model name
- operator: '==',
- // rule operator
- label: '',
- // label shown when editing fields
- choiceType: 'input',
- // input, select
- fieldTypes: [],
- // auto connect this conditions with these field types
- data: {
- conditions: false,
- // the parent instance
- field: false,
- // the field which we query against
- rule: {} // the rule [field, operator, value]
-
- },
- events: {
- 'change': 'change',
- 'keyup': 'change',
- 'enableField': 'change',
- 'disableField': 'change'
- },
- setup: function (props) {
- $.extend(this.data, props);
- },
- getEventTarget: function ($el, event) {
- return $el || this.get('field').$el;
- },
- change: function (e, $el) {
- this.get('conditions').change(e);
- },
- match: function (rule, field) {
- return false;
- },
- calculate: function () {
- return this.match(this.get('rule'), this.get('field'));
- },
- choices: function (field) {
- return ' ';
- }
- });
- /**
- * acf.newCondition
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.newCondition = function (rule, conditions) {
- // currently setting up conditions for fieldX, this field is the 'target'
- var target = conditions.get('field'); // use the 'target' to find the 'trigger' field.
- // - this field is used to setup the conditional logic events
-
- var field = target.getField(rule.field); // bail ealry if no target or no field (possible if field doesn't exist due to HTML error)
-
- if (!target || !field) {
- return false;
- } // vars
-
-
- var args = {
- rule: rule,
- target: target,
- conditions: conditions,
- field: field
- }; // vars
-
- var fieldType = field.get('type');
- var operator = rule.operator; // get avaibale conditions
-
- var conditionTypes = acf.getConditionTypes({
- fieldType: fieldType,
- operator: operator
- }); // instantiate
-
- var model = conditionTypes[0] || acf.Condition; // instantiate
-
- var condition = new model(args); // return
-
- return condition;
- };
- /**
- * mid
- *
- * Calculates the model ID for a field type
- *
- * @date 15/12/17
- * @since 5.6.5
- *
- * @param string type
- * @return string
- */
-
-
- var modelId = function (type) {
- return acf.strPascalCase(type || '') + 'Condition';
- };
- /**
- * acf.registerConditionType
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.registerConditionType = function (model) {
- // vars
- var proto = model.prototype;
- var type = proto.type;
- var mid = modelId(type); // store model
-
- acf.models[mid] = model; // store reference
-
- storage.push(type);
- };
- /**
- * acf.getConditionType
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.getConditionType = function (type) {
- var mid = modelId(type);
- return acf.models[mid] || false;
- };
- /**
- * acf.registerConditionForFieldType
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.registerConditionForFieldType = function (conditionType, fieldType) {
- // get model
- var model = acf.getConditionType(conditionType); // append
-
- if (model) {
- model.prototype.fieldTypes.push(fieldType);
- }
- };
- /**
- * acf.getConditionTypes
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.getConditionTypes = function (args) {
- // defaults
- args = acf.parseArgs(args, {
- fieldType: '',
- operator: ''
- }); // clonse available types
-
- var types = []; // loop
-
- storage.map(function (type) {
- // vars
- var model = acf.getConditionType(type);
- var ProtoFieldTypes = model.prototype.fieldTypes;
- var ProtoOperator = model.prototype.operator; // check fieldType
-
- if (args.fieldType && ProtoFieldTypes.indexOf(args.fieldType) === -1) {
- return;
- } // check operator
-
-
- if (args.operator && ProtoOperator !== args.operator) {
- return;
- } // append
-
-
- types.push(model);
- }); // return
-
- return types;
- };
+ /**
+ * mid
+ *
+ * Calculates the model ID for a field type
+ *
+ * @date 15/12/17
+ * @since 5.6.5
+ *
+ * @param string type
+ * @return string
+ */
+
+ var modelId = function( type ) {
+ return acf.strPascalCase( type || '' ) + 'Condition';
+ };
+
+ /**
+ * acf.registerConditionType
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.registerConditionType = function( model ){
+
+ // vars
+ var proto = model.prototype;
+ var type = proto.type;
+ var mid = modelId( type );
+
+ // store model
+ acf.models[ mid ] = model;
+
+ // store reference
+ storage.push( type );
+ };
+
+ /**
+ * acf.getConditionType
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.getConditionType = function( type ){
+ var mid = modelId( type );
+ return acf.models[ mid ] || false;
+ }
+
+ /**
+ * acf.registerConditionForFieldType
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.registerConditionForFieldType = function( conditionType, fieldType ){
+
+ // get model
+ var model = acf.getConditionType( conditionType );
+
+ // append
+ if( model ) {
+ model.prototype.fieldTypes.push( fieldType );
+ }
+ };
+
+ /**
+ * acf.getConditionTypes
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.getConditionTypes = function( args ){
+
+ // defaults
+ args = acf.parseArgs(args, {
+ fieldType: '',
+ operator: ''
+ });
+
+ // clonse available types
+ var types = [];
+
+ // loop
+ storage.map(function( type ){
+
+ // vars
+ var model = acf.getConditionType(type);
+ var ProtoFieldTypes = model.prototype.fieldTypes;
+ var ProtoOperator = model.prototype.operator;
+
+ // check fieldType
+ if( args.fieldType && ProtoFieldTypes.indexOf( args.fieldType ) === -1 ) {
+ return;
+ }
+
+ // check operator
+ if( args.operator && ProtoOperator !== args.operator ) {
+ return;
+ }
+
+ // append
+ types.push( model );
+ });
+
+ // return
+ return types;
+ };
+
})(jQuery);
+(function($, undefined){
+
+ // vars
+ var CONTEXT = 'conditional_logic';
+
+ /**
+ * conditionsManager
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var conditionsManager = new acf.Model({
+
+ id: 'conditionsManager',
+
+ priority: 20, // run actions later
+
+ actions: {
+ 'new_field': 'onNewField',
+ },
+
+ onNewField: function( field ){
+ if( field.has('conditions') ) {
+ field.getConditions().render();
+ }
+ },
+ });
+
+ /**
+ * acf.Field.prototype.getField
+ *
+ * Finds a field that is related to another field
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var getSiblingField = function( field, key ){
+
+ // find sibling (very fast)
+ var fields = acf.getFields({
+ key: key,
+ sibling: field.$el,
+ suppressFilters: true,
+ });
+
+ // find sibling-children (fast)
+ // needed for group fields, accordions, etc
+ if( !fields.length ) {
+ fields = acf.getFields({
+ key: key,
+ parent: field.$el.parent(),
+ suppressFilters: true,
+ });
+ }
+
+ // return
+ if( fields.length ) {
+ return fields[0];
+ }
+ return false;
+ };
+
+ acf.Field.prototype.getField = function( key ){
+
+ // get sibling field
+ var field = getSiblingField( this, key );
+
+ // return early
+ if( field ) {
+ return field;
+ }
+
+ // move up through each parent and try again
+ var parents = this.parents();
+ for( var i = 0; i < parents.length; i++ ) {
+
+ // get sibling field
+ field = getSiblingField( parents[i], key );
+
+ // return early
+ if( field ) {
+ return field;
+ }
+ }
+
+ // return
+ return false;
+ };
+
+
+ /**
+ * acf.Field.prototype.getConditions
+ *
+ * Returns the field's conditions instance
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.Field.prototype.getConditions = function(){
+
+ // instantiate
+ if( !this.conditions ) {
+ this.conditions = new Conditions( this );
+ }
+
+ // return
+ return this.conditions;
+ };
+
+
+ /**
+ * Conditions
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+ var timeout = false;
+ var Conditions = acf.Model.extend({
+
+ id: 'Conditions',
+
+ data: {
+ field: false, // The field with "data-conditions" (target).
+ timeStamp: false, // Reference used during "change" event.
+ groups: [], // The groups of condition instances.
+ },
+
+ setup: function( field ){
+
+ // data
+ this.data.field = field;
+
+ // vars
+ var conditions = field.get('conditions');
+
+ // detect groups
+ if( conditions instanceof Array ) {
+
+ // detect groups
+ if( conditions[0] instanceof Array ) {
-(function ($, undefined) {
- // vars
- var CONTEXT = 'conditional_logic';
- /**
- * conditionsManager
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var conditionsManager = new acf.Model({
- id: 'conditionsManager',
- priority: 20,
- // run actions later
- actions: {
- 'new_field': 'onNewField'
- },
- onNewField: function (field) {
- if (field.has('conditions')) {
- field.getConditions().render();
- }
- }
- });
- /**
- * acf.Field.prototype.getField
- *
- * Finds a field that is related to another field
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var getSiblingField = function (field, key) {
- // find sibling (very fast)
- var fields = acf.getFields({
- key: key,
- sibling: field.$el,
- suppressFilters: true
- }); // find sibling-children (fast)
- // needed for group fields, accordions, etc
-
- if (!fields.length) {
- fields = acf.getFields({
- key: key,
- parent: field.$el.parent(),
- suppressFilters: true
- });
- } // return
-
-
- if (fields.length) {
- return fields[0];
- }
-
- return false;
- };
-
- acf.Field.prototype.getField = function (key) {
- // get sibling field
- var field = getSiblingField(this, key); // return early
-
- if (field) {
- return field;
- } // move up through each parent and try again
-
-
- var parents = this.parents();
-
- for (var i = 0; i < parents.length; i++) {
- // get sibling field
- field = getSiblingField(parents[i], key); // return early
-
- if (field) {
- return field;
- }
- } // return
-
-
- return false;
- };
- /**
- * acf.Field.prototype.getConditions
- *
- * Returns the field's conditions instance
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.Field.prototype.getConditions = function () {
- // instantiate
- if (!this.conditions) {
- this.conditions = new Conditions(this);
- } // return
-
-
- return this.conditions;
- };
- /**
- * Conditions
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- var timeout = false;
- var Conditions = acf.Model.extend({
- id: 'Conditions',
- data: {
- field: false,
- // The field with "data-conditions" (target).
- timeStamp: false,
- // Reference used during "change" event.
- groups: [] // The groups of condition instances.
-
- },
- setup: function (field) {
- // data
- this.data.field = field; // vars
-
- var conditions = field.get('conditions'); // detect groups
-
- if (conditions instanceof Array) {
- // detect groups
- if (conditions[0] instanceof Array) {
- // loop
- conditions.map(function (rules, i) {
- this.addRules(rules, i);
- }, this); // detect rules
- } else {
- this.addRules(conditions);
- } // detect rule
-
- } else {
- this.addRule(conditions);
- }
- },
- change: function (e) {
- // this function may be triggered multiple times per event due to multiple condition classes
- // compare timestamp to allow only 1 trigger per event
- if (this.get('timeStamp') === e.timeStamp) {
- return false;
- } else {
- this.set('timeStamp', e.timeStamp, true);
- } // render condition and store result
-
-
- var changed = this.render();
- },
- render: function () {
- return this.calculate() ? this.show() : this.hide();
- },
- show: function () {
- return this.get('field').showEnable(this.cid, CONTEXT);
- },
- hide: function () {
- return this.get('field').hideDisable(this.cid, CONTEXT);
- },
- calculate: function () {
- // vars
- var pass = false; // loop
-
- this.getGroups().map(function (group) {
- // igrnore this group if another group passed
- if (pass) return; // find passed
-
- var passed = group.filter(function (condition) {
- return condition.calculate();
- }); // if all conditions passed, update the global var
-
- if (passed.length == group.length) {
- pass = true;
- }
- });
- return pass;
- },
- hasGroups: function () {
- return this.data.groups != null;
- },
- getGroups: function () {
- return this.data.groups;
- },
- addGroup: function () {
- var group = [];
- this.data.groups.push(group);
- return group;
- },
- hasGroup: function (i) {
- return this.data.groups[i] != null;
- },
- getGroup: function (i) {
- return this.data.groups[i];
- },
- removeGroup: function (i) {
- this.data.groups[i].delete;
- return this;
- },
- addRules: function (rules, group) {
- rules.map(function (rule) {
- this.addRule(rule, group);
- }, this);
- },
- addRule: function (rule, group) {
- // defaults
- group = group || 0; // vars
-
- var groupArray; // get group
-
- if (this.hasGroup(group)) {
- groupArray = this.getGroup(group);
- } else {
- groupArray = this.addGroup();
- } // instantiate
-
-
- var condition = acf.newCondition(rule, this); // bail ealry if condition failed (field did not exist)
-
- if (!condition) {
- return false;
- } // add rule
-
-
- groupArray.push(condition);
- },
- hasRule: function () {},
- getRule: function (rule, group) {
- // defaults
- rule = rule || 0;
- group = group || 0;
- return this.data.groups[group][rule];
- },
- removeRule: function () {}
- });
+ // loop
+ conditions.map(function(rules, i){
+ this.addRules( rules, i );
+ }, this);
+
+ // detect rules
+ } else {
+ this.addRules( conditions );
+ }
+
+ // detect rule
+ } else {
+ this.addRule( conditions );
+ }
+ },
+
+ change: function( e ){
+
+ // this function may be triggered multiple times per event due to multiple condition classes
+ // compare timestamp to allow only 1 trigger per event
+ if( this.get('timeStamp') === e.timeStamp ) {
+ return false;
+ } else {
+ this.set('timeStamp', e.timeStamp, true);
+ }
+
+ // render condition and store result
+ var changed = this.render();
+ },
+
+ render: function(){
+ return this.calculate() ? this.show() : this.hide();
+ },
+
+ show: function(){
+ return this.get('field').showEnable(this.cid, CONTEXT);
+ },
+
+ hide: function(){
+ return this.get('field').hideDisable(this.cid, CONTEXT);
+ },
+
+ calculate: function(){
+
+ // vars
+ var pass = false;
+
+ // loop
+ this.getGroups().map(function( group ){
+
+ // igrnore this group if another group passed
+ if( pass ) return;
+
+ // find passed
+ var passed = group.filter(function(condition){
+ return condition.calculate();
+ });
+
+ // if all conditions passed, update the global var
+ if( passed.length == group.length ) {
+ pass = true;
+ }
+ });
+
+ return pass;
+ },
+
+ hasGroups: function(){
+ return this.data.groups != null;
+ },
+
+ getGroups: function(){
+ return this.data.groups;
+ },
+
+ addGroup: function(){
+ var group = [];
+ this.data.groups.push( group );
+ return group;
+ },
+
+ hasGroup: function( i ){
+ return this.data.groups[i] != null;
+ },
+
+ getGroup: function( i ){
+ return this.data.groups[i];
+ },
+
+ removeGroup: function( i ){
+ this.data.groups[i].delete;
+ return this;
+ },
+
+ addRules: function( rules, group ){
+ rules.map(function( rule ){
+ this.addRule( rule, group );
+ }, this);
+ },
+
+ addRule: function( rule, group ){
+
+ // defaults
+ group = group || 0;
+
+ // vars
+ var groupArray;
+
+ // get group
+ if( this.hasGroup(group) ) {
+ groupArray = this.getGroup(group);
+ } else {
+ groupArray = this.addGroup();
+ }
+
+ // instantiate
+ var condition = acf.newCondition( rule, this );
+
+ // bail ealry if condition failed (field did not exist)
+ if( !condition ) {
+ return false;
+ }
+
+ // add rule
+ groupArray.push(condition);
+ },
+
+ hasRule: function(){
+
+ },
+
+ getRule: function( rule, group ){
+
+ // defaults
+ rule = rule || 0;
+ group = group || 0;
+
+ return this.data.groups[ group ][ rule ];
+ },
+
+ removeRule: function(){
+
+ }
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- var __ = acf.__;
-
- var parseString = function (val) {
- return val ? '' + val : '';
- };
-
- var isEqualTo = function (v1, v2) {
- return parseString(v1).toLowerCase() === parseString(v2).toLowerCase();
- };
-
- var isEqualToNumber = function (v1, v2) {
- return parseFloat(v1) === parseFloat(v2);
- };
-
- var isGreaterThan = function (v1, v2) {
- return parseFloat(v1) > parseFloat(v2);
- };
-
- var isLessThan = function (v1, v2) {
- return parseFloat(v1) < parseFloat(v2);
- };
-
- var inArray = function (v1, array) {
- // cast all values as string
- array = array.map(function (v2) {
- return parseString(v2);
- });
- return array.indexOf(v1) > -1;
- };
-
- var containsString = function (haystack, needle) {
- return parseString(haystack).indexOf(parseString(needle)) > -1;
- };
-
- var matchesPattern = function (v1, pattern) {
- var regexp = new RegExp(parseString(pattern), 'gi');
- return parseString(v1).match(regexp);
- };
- /**
- * hasValue
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
-
- var HasValue = acf.Condition.extend({
- type: 'hasValue',
- operator: '!=empty',
- label: __('Has any value'),
- fieldTypes: ['text', 'textarea', 'number', 'range', 'email', 'url', 'password', 'image', 'file', 'wysiwyg', 'oembed', 'select', 'checkbox', 'radio', 'button_group', 'link', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user', 'google_map', 'date_picker', 'date_time_picker', 'time_picker', 'color_picker'],
- match: function (rule, field) {
- return field.val() ? true : false;
- },
- choices: function (fieldObject) {
- return ' ';
- }
- });
- acf.registerConditionType(HasValue);
- /**
- * hasValue
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var HasNoValue = HasValue.extend({
- type: 'hasNoValue',
- operator: '==empty',
- label: __('Has no value'),
- match: function (rule, field) {
- return !HasValue.prototype.match.apply(this, arguments);
- }
- });
- acf.registerConditionType(HasNoValue);
- /**
- * EqualTo
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var EqualTo = acf.Condition.extend({
- type: 'equalTo',
- operator: '==',
- label: __('Value is equal to'),
- fieldTypes: ['text', 'textarea', 'number', 'range', 'email', 'url', 'password'],
- match: function (rule, field) {
- if (acf.isNumeric(rule.value)) {
- return isEqualToNumber(rule.value, field.val());
- } else {
- return isEqualTo(rule.value, field.val());
- }
- },
- choices: function (fieldObject) {
- return ' ';
- }
- });
- acf.registerConditionType(EqualTo);
- /**
- * NotEqualTo
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var NotEqualTo = EqualTo.extend({
- type: 'notEqualTo',
- operator: '!=',
- label: __('Value is not equal to'),
- match: function (rule, field) {
- return !EqualTo.prototype.match.apply(this, arguments);
- }
- });
- acf.registerConditionType(NotEqualTo);
- /**
- * PatternMatch
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var PatternMatch = acf.Condition.extend({
- type: 'patternMatch',
- operator: '==pattern',
- label: __('Value matches pattern'),
- fieldTypes: ['text', 'textarea', 'email', 'url', 'password', 'wysiwyg'],
- match: function (rule, field) {
- return matchesPattern(field.val(), rule.value);
- },
- choices: function (fieldObject) {
- return ' ';
- }
- });
- acf.registerConditionType(PatternMatch);
- /**
- * Contains
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var Contains = acf.Condition.extend({
- type: 'contains',
- operator: '==contains',
- label: __('Value contains'),
- fieldTypes: ['text', 'textarea', 'number', 'email', 'url', 'password', 'wysiwyg', 'oembed', 'select'],
- match: function (rule, field) {
- return containsString(field.val(), rule.value);
- },
- choices: function (fieldObject) {
- return ' ';
- }
- });
- acf.registerConditionType(Contains);
- /**
- * TrueFalseEqualTo
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var TrueFalseEqualTo = EqualTo.extend({
- type: 'trueFalseEqualTo',
- choiceType: 'select',
- fieldTypes: ['true_false'],
- choices: function (field) {
- return [{
- id: 1,
- text: __('Checked')
- }];
- }
- });
- acf.registerConditionType(TrueFalseEqualTo);
- /**
- * TrueFalseNotEqualTo
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var TrueFalseNotEqualTo = NotEqualTo.extend({
- type: 'trueFalseNotEqualTo',
- choiceType: 'select',
- fieldTypes: ['true_false'],
- choices: function (field) {
- return [{
- id: 1,
- text: __('Checked')
- }];
- }
- });
- acf.registerConditionType(TrueFalseNotEqualTo);
- /**
- * SelectEqualTo
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var SelectEqualTo = acf.Condition.extend({
- type: 'selectEqualTo',
- operator: '==',
- label: __('Value is equal to'),
- fieldTypes: ['select', 'checkbox', 'radio', 'button_group'],
- match: function (rule, field) {
- var val = field.val();
-
- if (val instanceof Array) {
- return inArray(rule.value, val);
- } else {
- return isEqualTo(rule.value, val);
- }
- },
- choices: function (fieldObject) {
- // vars
- var choices = [];
- var lines = fieldObject.$setting('choices textarea').val().split("\n"); // allow null
-
- if (fieldObject.$input('allow_null').prop('checked')) {
- choices.push({
- id: '',
- text: __('Null')
- });
- } // loop
-
-
- lines.map(function (line) {
- // split
- line = line.split(':'); // default label to value
-
- line[1] = line[1] || line[0]; // append
-
- choices.push({
- id: line[0].trim(),
- text: line[1].trim()
- });
- }); // return
-
- return choices;
- }
- });
- acf.registerConditionType(SelectEqualTo);
- /**
- * SelectNotEqualTo
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var SelectNotEqualTo = SelectEqualTo.extend({
- type: 'selectNotEqualTo',
- operator: '!=',
- label: __('Value is not equal to'),
- match: function (rule, field) {
- return !SelectEqualTo.prototype.match.apply(this, arguments);
- }
- });
- acf.registerConditionType(SelectNotEqualTo);
- /**
- * GreaterThan
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var GreaterThan = acf.Condition.extend({
- type: 'greaterThan',
- operator: '>',
- label: __('Value is greater than'),
- fieldTypes: ['number', 'range'],
- match: function (rule, field) {
- var val = field.val();
-
- if (val instanceof Array) {
- val = val.length;
- }
-
- return isGreaterThan(val, rule.value);
- },
- choices: function (fieldObject) {
- return ' ';
- }
- });
- acf.registerConditionType(GreaterThan);
- /**
- * LessThan
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var LessThan = GreaterThan.extend({
- type: 'lessThan',
- operator: '<',
- label: __('Value is less than'),
- match: function (rule, field) {
- var val = field.val();
-
- if (val instanceof Array) {
- val = val.length;
- }
-
- return isLessThan(val, rule.value);
- },
- choices: function (fieldObject) {
- return ' ';
- }
- });
- acf.registerConditionType(LessThan);
- /**
- * SelectedGreaterThan
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var SelectionGreaterThan = GreaterThan.extend({
- type: 'selectionGreaterThan',
- label: __('Selection is greater than'),
- fieldTypes: ['checkbox', 'select', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user']
- });
- acf.registerConditionType(SelectionGreaterThan);
- /**
- * SelectedGreaterThan
- *
- * description
- *
- * @date 1/2/18
- * @since 5.6.5
- *
- * @param void
- * @return void
- */
-
- var SelectionLessThan = LessThan.extend({
- type: 'selectionLessThan',
- label: __('Selection is less than'),
- fieldTypes: ['checkbox', 'select', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user']
- });
- acf.registerConditionType(SelectionLessThan);
+(function($, undefined){
+
+ var __ = acf.__;
+
+ var parseString = function( val ){
+ return val ? '' + val : '';
+ };
+
+ var isEqualTo = function( v1, v2 ){
+ return ( parseString(v1).toLowerCase() === parseString(v2).toLowerCase() );
+ };
+
+ var isEqualToNumber = function( v1, v2 ){
+ return ( parseFloat(v1) === parseFloat(v2) );
+ };
+
+ var isGreaterThan = function( v1, v2 ){
+ return ( parseFloat(v1) > parseFloat(v2) );
+ };
+
+ var isLessThan = function( v1, v2 ){
+ return ( parseFloat(v1) < parseFloat(v2) );
+ };
+
+ var inArray = function( v1, array ){
+
+ // cast all values as string
+ array = array.map(function(v2){
+ return parseString(v2);
+ });
+
+ return (array.indexOf( v1 ) > -1);
+ }
+
+ var containsString = function( haystack, needle ){
+ return ( parseString(haystack).indexOf( parseString(needle) ) > -1 );
+ };
+
+ var matchesPattern = function( v1, pattern ){
+ var regexp = new RegExp(parseString(pattern), 'gi');
+ return parseString(v1).match( regexp );
+ };
+
+ /**
+ * hasValue
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var HasValue = acf.Condition.extend({
+ type: 'hasValue',
+ operator: '!=empty',
+ label: __('Has any value'),
+ fieldTypes: [ 'text', 'textarea', 'number', 'range', 'email', 'url', 'password', 'image', 'file', 'wysiwyg', 'oembed', 'select', 'checkbox', 'radio', 'button_group', 'link', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user', 'google_map', 'date_picker', 'date_time_picker', 'time_picker', 'color_picker' ],
+ match: function( rule, field ){
+ return (field.val() ? true : false);
+ },
+ choices: function( fieldObject ){
+ return ' ';
+ }
+ });
+
+ acf.registerConditionType( HasValue );
+
+ /**
+ * hasValue
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var HasNoValue = HasValue.extend({
+ type: 'hasNoValue',
+ operator: '==empty',
+ label: __('Has no value'),
+ match: function( rule, field ){
+ return !HasValue.prototype.match.apply(this, arguments);
+ }
+ });
+
+ acf.registerConditionType( HasNoValue );
+
+
+
+ /**
+ * EqualTo
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var EqualTo = acf.Condition.extend({
+ type: 'equalTo',
+ operator: '==',
+ label: __('Value is equal to'),
+ fieldTypes: [ 'text', 'textarea', 'number', 'range', 'email', 'url', 'password' ],
+ match: function( rule, field ){
+ if( acf.isNumeric(rule.value) ) {
+ return isEqualToNumber( rule.value, field.val() );
+ } else {
+ return isEqualTo( rule.value, field.val() );
+ }
+ },
+ choices: function( fieldObject ){
+ return ' ';
+ }
+ });
+
+ acf.registerConditionType( EqualTo );
+
+ /**
+ * NotEqualTo
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var NotEqualTo = EqualTo.extend({
+ type: 'notEqualTo',
+ operator: '!=',
+ label: __('Value is not equal to'),
+ match: function( rule, field ){
+ return !EqualTo.prototype.match.apply(this, arguments);
+ }
+ });
+
+ acf.registerConditionType( NotEqualTo );
+
+ /**
+ * PatternMatch
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var PatternMatch = acf.Condition.extend({
+ type: 'patternMatch',
+ operator: '==pattern',
+ label: __('Value matches pattern'),
+ fieldTypes: [ 'text', 'textarea', 'email', 'url', 'password', 'wysiwyg' ],
+ match: function( rule, field ){
+ return matchesPattern( field.val(), rule.value );
+ },
+ choices: function( fieldObject ){
+ return ' ';
+ }
+ });
+
+ acf.registerConditionType( PatternMatch );
+
+ /**
+ * Contains
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var Contains = acf.Condition.extend({
+ type: 'contains',
+ operator: '==contains',
+ label: __('Value contains'),
+ fieldTypes: [ 'text', 'textarea', 'number', 'email', 'url', 'password', 'wysiwyg', 'oembed', 'select' ],
+ match: function( rule, field ){
+ return containsString( field.val(), rule.value );
+ },
+ choices: function( fieldObject ){
+ return ' ';
+ }
+ });
+
+ acf.registerConditionType( Contains );
+
+ /**
+ * TrueFalseEqualTo
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var TrueFalseEqualTo = EqualTo.extend({
+ type: 'trueFalseEqualTo',
+ choiceType: 'select',
+ fieldTypes: [ 'true_false' ],
+ choices: function( field ){
+ return [
+ {
+ id: 1,
+ text: __('Checked')
+ }
+ ];
+ },
+ });
+
+ acf.registerConditionType( TrueFalseEqualTo );
+
+ /**
+ * TrueFalseNotEqualTo
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var TrueFalseNotEqualTo = NotEqualTo.extend({
+ type: 'trueFalseNotEqualTo',
+ choiceType: 'select',
+ fieldTypes: [ 'true_false' ],
+ choices: function( field ){
+ return [
+ {
+ id: 1,
+ text: __('Checked')
+ }
+ ];
+ },
+ });
+
+ acf.registerConditionType( TrueFalseNotEqualTo );
+
+ /**
+ * SelectEqualTo
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var SelectEqualTo = acf.Condition.extend({
+ type: 'selectEqualTo',
+ operator: '==',
+ label: __('Value is equal to'),
+ fieldTypes: [ 'select', 'checkbox', 'radio', 'button_group' ],
+ match: function( rule, field ){
+ var val = field.val();
+ if( val instanceof Array ) {
+ return inArray( rule.value, val );
+ } else {
+ return isEqualTo( rule.value, val );
+ }
+ },
+ choices: function( fieldObject ){
+
+ // vars
+ var choices = [];
+ var lines = fieldObject.$setting('choices textarea').val().split("\n");
+
+ // allow null
+ if( fieldObject.$input('allow_null').prop('checked') ) {
+ choices.push({
+ id: '',
+ text: __('Null')
+ });
+ }
+
+ // loop
+ lines.map(function( line ){
+
+ // split
+ line = line.split(':');
+
+ // default label to value
+ line[1] = line[1] || line[0];
+
+ // append
+ choices.push({
+ id: line[0].trim(),
+ text: line[1].trim()
+ });
+ });
+
+ // return
+ return choices;
+ },
+ });
+
+ acf.registerConditionType( SelectEqualTo );
+
+ /**
+ * SelectNotEqualTo
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var SelectNotEqualTo = SelectEqualTo.extend({
+ type: 'selectNotEqualTo',
+ operator: '!=',
+ label: __('Value is not equal to'),
+ match: function( rule, field ){
+ return !SelectEqualTo.prototype.match.apply(this, arguments);
+ }
+ });
+
+ acf.registerConditionType( SelectNotEqualTo );
+
+ /**
+ * GreaterThan
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var GreaterThan = acf.Condition.extend({
+ type: 'greaterThan',
+ operator: '>',
+ label: __('Value is greater than'),
+ fieldTypes: [ 'number', 'range' ],
+ match: function( rule, field ){
+ var val = field.val();
+ if( val instanceof Array ) {
+ val = val.length;
+ }
+ return isGreaterThan( val, rule.value );
+ },
+ choices: function( fieldObject ){
+ return ' ';
+ }
+ });
+
+ acf.registerConditionType( GreaterThan );
+
+
+ /**
+ * LessThan
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var LessThan = GreaterThan.extend({
+ type: 'lessThan',
+ operator: '<',
+ label: __('Value is less than'),
+ match: function( rule, field ){
+ var val = field.val();
+ if( val instanceof Array ) {
+ val = val.length;
+ }
+ return isLessThan( val, rule.value );
+ },
+ choices: function( fieldObject ){
+ return ' ';
+ }
+ });
+
+ acf.registerConditionType( LessThan );
+
+ /**
+ * SelectedGreaterThan
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var SelectionGreaterThan = GreaterThan.extend({
+ type: 'selectionGreaterThan',
+ label: __('Selection is greater than'),
+ fieldTypes: [ 'checkbox', 'select', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user' ],
+ });
+
+ acf.registerConditionType( SelectionGreaterThan );
+
+ /**
+ * SelectedGreaterThan
+ *
+ * description
+ *
+ * @date 1/2/18
+ * @since 5.6.5
+ *
+ * @param void
+ * @return void
+ */
+
+ var SelectionLessThan = LessThan.extend({
+ type: 'selectionLessThan',
+ label: __('Selection is less than'),
+ fieldTypes: [ 'checkbox', 'select', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user' ],
+ });
+
+ acf.registerConditionType( SelectionLessThan );
+
})(jQuery);
-
-(function ($, undefined) {
- acf.unload = new acf.Model({
- wait: 'load',
- active: true,
- changed: false,
- actions: {
- 'validation_failure': 'startListening',
- 'validation_success': 'stopListening'
- },
- events: {
- 'change form .acf-field': 'startListening',
- 'submit form': 'stopListening'
- },
- enable: function () {
- this.active = true;
- },
- disable: function () {
- this.active = false;
- },
- reset: function () {
- this.stopListening();
- },
- startListening: function () {
- // bail ealry if already changed, not active
- if (this.changed || !this.active) {
- return;
- } // update
-
-
- this.changed = true; // add event
-
- $(window).on('beforeunload', this.onUnload);
- },
- stopListening: function () {
- // update
- this.changed = false; // remove event
-
- $(window).off('beforeunload', this.onUnload);
- },
- onUnload: function () {
- return acf.__('The changes you made will be lost if you navigate away from this page');
- }
- });
+(function($, undefined){
+
+ acf.unload = new acf.Model({
+
+ wait: 'load',
+ active: true,
+ changed: false,
+
+ actions: {
+ 'validation_failure': 'startListening',
+ 'validation_success': 'stopListening'
+ },
+
+ events: {
+ 'change form .acf-field': 'startListening',
+ 'submit form': 'stopListening'
+ },
+
+ enable: function(){
+ this.active = true;
+ },
+
+ disable: function(){
+ this.active = false;
+ },
+
+ reset: function(){
+ this.stopListening();
+ },
+
+ startListening: function(){
+
+ // bail ealry if already changed, not active
+ if( this.changed || !this.active ) {
+ return;
+ }
+
+ // update
+ this.changed = true;
+
+ // add event
+ $(window).on('beforeunload', this.onUnload);
+
+ },
+
+ stopListening: function(){
+
+ // update
+ this.changed = false;
+
+ // remove event
+ $(window).off('beforeunload', this.onUnload);
+
+ },
+
+ onUnload: function(){
+ return acf.__('The changes you made will be lost if you navigate away from this page');
+ }
+
+ });
+
})(jQuery);
+(function($, undefined){
+
+ /**
+ * postboxManager
+ *
+ * Manages postboxes on the screen.
+ *
+ * @date 25/5/19
+ * @since 5.8.1
+ *
+ * @param void
+ * @return void
+ */
+ var postboxManager = new acf.Model({
+ wait: 'prepare',
+ priority: 1,
+ initialize: function(){
+ (acf.get('postboxes') || []).map( acf.newPostbox );
+ },
+ });
+
+ /**
+ * acf.getPostbox
+ *
+ * Returns a postbox instance.
+ *
+ * @date 23/9/18
+ * @since 5.7.7
+ *
+ * @param mixed $el Either a jQuery element or the postbox id.
+ * @return object
+ */
+ acf.getPostbox = function( $el ){
+
+ // allow string parameter
+ if( typeof arguments[0] == 'string' ) {
+ $el = $('#' + arguments[0]);
+ }
+
+ // return instance
+ return acf.getInstance( $el );
+ };
+
+ /**
+ * acf.getPostboxes
+ *
+ * Returns an array of postbox instances.
+ *
+ * @date 23/9/18
+ * @since 5.7.7
+ *
+ * @param void
+ * @return array
+ */
+ acf.getPostboxes = function(){
+ return acf.getInstances( $('.acf-postbox') );
+ };
+
+ /**
+ * acf.newPostbox
+ *
+ * Returns a new postbox instance for the given props.
+ *
+ * @date 20/9/18
+ * @since 5.7.6
+ *
+ * @param object props The postbox properties.
+ * @return object
+ */
+ acf.newPostbox = function( props ){
+ return new acf.models.Postbox( props );
+ };
+
+ /**
+ * acf.models.Postbox
+ *
+ * The postbox model.
+ *
+ * @date 20/9/18
+ * @since 5.7.6
+ *
+ * @param void
+ * @return void
+ */
+ acf.models.Postbox = acf.Model.extend({
+
+ data: {
+ id: '',
+ key: '',
+ style: 'default',
+ label: 'top',
+ edit: ''
+ },
+
+ setup: function( props ){
+
+ // compatibilty
+ if( props.editLink ) {
+ props.edit = props.editLink;
+ }
+
+ // extend data
+ $.extend(this.data, props);
+
+ // set $el
+ this.$el = this.$postbox();
+ },
+
+ $postbox: function(){
+ return $('#' + this.get('id'));
+ },
+
+ $hide: function(){
+ return $('#' + this.get('id') + '-hide');
+ },
+
+ $hideLabel: function(){
+ return this.$hide().parent();
+ },
+
+ $hndle: function(){
+ return this.$('> .hndle');
+ },
-(function ($, undefined) {
- /**
- * postboxManager
- *
- * Manages postboxes on the screen.
- *
- * @date 25/5/19
- * @since 5.8.1
- *
- * @param void
- * @return void
- */
- var postboxManager = new acf.Model({
- wait: 'prepare',
- priority: 1,
- initialize: function () {
- (acf.get('postboxes') || []).map(acf.newPostbox);
- }
- });
- /**
- * acf.getPostbox
- *
- * Returns a postbox instance.
- *
- * @date 23/9/18
- * @since 5.7.7
- *
- * @param mixed $el Either a jQuery element or the postbox id.
- * @return object
- */
-
- acf.getPostbox = function ($el) {
- // allow string parameter
- if (typeof arguments[0] == 'string') {
- $el = $('#' + arguments[0]);
- } // return instance
-
-
- return acf.getInstance($el);
- };
- /**
- * acf.getPostboxes
- *
- * Returns an array of postbox instances.
- *
- * @date 23/9/18
- * @since 5.7.7
- *
- * @param void
- * @return array
- */
-
-
- acf.getPostboxes = function () {
- return acf.getInstances($('.acf-postbox'));
- };
- /**
- * acf.newPostbox
- *
- * Returns a new postbox instance for the given props.
- *
- * @date 20/9/18
- * @since 5.7.6
- *
- * @param object props The postbox properties.
- * @return object
- */
-
-
- acf.newPostbox = function (props) {
- return new acf.models.Postbox(props);
- };
- /**
- * acf.models.Postbox
- *
- * The postbox model.
- *
- * @date 20/9/18
- * @since 5.7.6
- *
- * @param void
- * @return void
- */
-
-
- acf.models.Postbox = acf.Model.extend({
- data: {
- id: '',
- key: '',
- style: 'default',
- label: 'top',
- edit: ''
- },
- setup: function (props) {
- // compatibilty
- if (props.editLink) {
- props.edit = props.editLink;
- } // extend data
-
-
- $.extend(this.data, props); // set $el
-
- this.$el = this.$postbox();
- },
- $postbox: function () {
- return $('#' + this.get('id'));
- },
- $hide: function () {
- return $('#' + this.get('id') + '-hide');
- },
- $hideLabel: function () {
- return this.$hide().parent();
- },
- $hndle: function () {
- return this.$('> .hndle');
- },
- $handleActions: function () {
- return this.$('> .postbox-header .handle-actions');
- },
- $inside: function () {
- return this.$('> .inside');
- },
- isVisible: function () {
- return this.$el.hasClass('acf-hidden');
- },
- initialize: function () {
- // Add default class.
- this.$el.addClass('acf-postbox'); // Remove 'hide-if-js class.
- // This class is added by WP to postboxes that are hidden via the "Screen Options" tab.
-
- this.$el.removeClass('hide-if-js'); // Add field group style class (ignore in block editor).
-
- if (acf.get('editor') !== 'block') {
- var style = this.get('style');
-
- if (style !== 'default') {
- this.$el.addClass(style);
- }
- } // Add .inside class.
-
-
- this.$inside().addClass('acf-fields').addClass('-' + this.get('label')); // Append edit link.
-
- var edit = this.get('edit');
-
- if (edit) {
- var html = ' ';
- var $handleActions = this.$handleActions();
-
- if ($handleActions.length) {
- $handleActions.prepend(html);
- } else {
- this.$hndle().append(html);
- }
- } // Show postbox.
-
-
- this.show();
- },
- show: function () {
- // Show label.
- this.$hideLabel().show(); // toggle on checkbox
-
- this.$hide().prop('checked', true); // Show postbox
-
- this.$el.show().removeClass('acf-hidden'); // Do action.
-
- acf.doAction('show_postbox', this);
- },
- enable: function () {
- acf.enable(this.$el, 'postbox');
- },
- showEnable: function () {
- this.enable();
- this.show();
- },
- hide: function () {
- // Hide label.
- this.$hideLabel().hide(); // Hide postbox
-
- this.$el.hide().addClass('acf-hidden'); // Do action.
-
- acf.doAction('hide_postbox', this);
- },
- disable: function () {
- acf.disable(this.$el, 'postbox');
- },
- hideDisable: function () {
- this.disable();
- this.hide();
- },
- html: function (html) {
- // Update HTML.
- this.$inside().html(html); // Do action.
-
- acf.doAction('append', this.$el);
- }
- });
+ $handleActions: function(){
+ return this.$('> .postbox-header .handle-actions');
+ },
+
+ $inside: function(){
+ return this.$('> .inside');
+ },
+
+ isVisible: function(){
+ return this.$el.hasClass('acf-hidden');
+ },
+
+ initialize: function(){
+
+ // Add default class.
+ this.$el.addClass('acf-postbox');
+
+ // Remove 'hide-if-js class.
+ // This class is added by WP to postboxes that are hidden via the "Screen Options" tab.
+ this.$el.removeClass('hide-if-js');
+
+ // Add field group style class (ignore in block editor).
+ if( acf.get('editor') !== 'block' ) {
+ var style = this.get('style');
+ if( style !== 'default' ) {
+ this.$el.addClass( style );
+ }
+ }
+
+ // Add .inside class.
+ this.$inside().addClass('acf-fields').addClass('-' + this.get('label'));
+
+ // Append edit link.
+ var edit = this.get('edit');
+ if( edit ) {
+ var html = ' ';
+ var $handleActions = this.$handleActions();
+ if( $handleActions.length ) {
+ $handleActions.prepend( html );
+ } else {
+ this.$hndle().append( html );
+ }
+ }
+
+ // Show postbox.
+ this.show();
+ },
+
+ show: function(){
+
+ // Show label.
+ this.$hideLabel().show();
+
+ // toggle on checkbox
+ this.$hide().prop('checked', true);
+
+ // Show postbox
+ this.$el.show().removeClass('acf-hidden');
+
+ // Do action.
+ acf.doAction('show_postbox', this);
+ },
+
+ enable: function(){
+ acf.enable( this.$el, 'postbox' );
+ },
+
+ showEnable: function(){
+ this.enable();
+ this.show();
+ },
+
+ hide: function(){
+
+ // Hide label.
+ this.$hideLabel().hide();
+
+ // Hide postbox
+ this.$el.hide().addClass('acf-hidden');
+
+ // Do action.
+ acf.doAction('hide_postbox', this);
+ },
+
+ disable: function(){
+ acf.disable( this.$el, 'postbox' );
+ },
+
+ hideDisable: function(){
+ this.disable();
+ this.hide();
+ },
+
+ html: function( html ){
+
+ // Update HTML.
+ this.$inside().html( html );
+
+ // Do action.
+ acf.doAction('append', this.$el);
+ }
+ });
+
})(jQuery);
+(function($, undefined){
+
+ /**
+ * acf.newMediaPopup
+ *
+ * description
+ *
+ * @date 10/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.newMediaPopup = function( args ){
+
+ // args
+ var popup = null;
+ var args = acf.parseArgs(args, {
+ mode: 'select', // 'select', 'edit'
+ title: '', // 'Upload Image'
+ button: '', // 'Select Image'
+ type: '', // 'image', ''
+ field: false, // field instance
+ allowedTypes: '', // '.jpg, .png, etc'
+ library: 'all', // 'all', 'uploadedTo'
+ multiple: false, // false, true, 'add'
+ attachment: 0, // the attachment to edit
+ autoOpen: true, // open the popup automatically
+ open: function(){}, // callback after close
+ select: function(){}, // callback after select
+ close: function(){} // callback after close
+ });
+
+ // initialize
+ if( args.mode == 'edit' ) {
+ popup = new acf.models.EditMediaPopup( args );
+ } else {
+ popup = new acf.models.SelectMediaPopup( args );
+ }
+
+ // open popup (allow frame customization before opening)
+ if( args.autoOpen ) {
+ setTimeout(function(){
+ popup.open();
+ }, 1);
+ }
+
+ // action
+ acf.doAction('new_media_popup', popup);
+
+ // return
+ return popup;
+ };
+
+
+ /**
+ * getPostID
+ *
+ * description
+ *
+ * @date 10/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var getPostID = function() {
+ var postID = acf.get('post_id');
+ return acf.isNumeric(postID) ? postID : 0;
+ }
+
+
+ /**
+ * acf.getMimeTypes
+ *
+ * description
+ *
+ * @date 11/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.getMimeTypes = function(){
+ return this.get('mimeTypes');
+ };
+
+ acf.getMimeType = function( name ){
+
+ // vars
+ var allTypes = acf.getMimeTypes();
+
+ // search
+ if( allTypes[name] !== undefined ) {
+ return allTypes[name];
+ }
+
+ // some types contain a mixed key such as "jpg|jpeg|jpe"
+ for( var key in allTypes ) {
+ if( key.indexOf(name) !== -1 ) {
+ return allTypes[key];
+ }
+ }
+
+ // return
+ return false;
+ };
+
+
+ /**
+ * MediaPopup
+ *
+ * description
+ *
+ * @date 10/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var MediaPopup = acf.Model.extend({
+
+ id: 'MediaPopup',
+ data: {},
+ defaults: {},
+ frame: false,
+
+ setup: function( props ){
+ $.extend(this.data, props);
+ },
+
+ initialize: function(){
+
+ // vars
+ var options = this.getFrameOptions();
+
+ // add states
+ this.addFrameStates( options );
+
+ // create frame
+ var frame = wp.media( options );
+
+ // add args reference
+ frame.acf = this;
+
+ // add events
+ this.addFrameEvents( frame, options );
+
+ // strore frame
+ this.frame = frame;
+ },
+
+ open: function(){
+ this.frame.open();
+ },
+
+ close: function(){
+ this.frame.close();
+ },
+
+ remove: function(){
+ this.frame.detach();
+ this.frame.remove();
+ },
+
+ getFrameOptions: function(){
+
+ // vars
+ var options = {
+ title: this.get('title'),
+ multiple: this.get('multiple'),
+ library: {},
+ states: []
+ };
+
+ // type
+ if( this.get('type') ) {
+ options.library.type = this.get('type');
+ }
+
+ // type
+ if( this.get('library') === 'uploadedTo' ) {
+ options.library.uploadedTo = getPostID();
+ }
+
+ // attachment
+ if( this.get('attachment') ) {
+ options.library.post__in = [ this.get('attachment') ];
+ }
+
+ // button
+ if( this.get('button') ) {
+ options.button = {
+ text: this.get('button')
+ };
+ }
+
+ // return
+ return options;
+ },
+
+ addFrameStates: function( options ){
+
+ // create query
+ var Query = wp.media.query( options.library );
+
+ // add _acfuploader
+ // this is super wack!
+ // if you add _acfuploader to the options.library args, new uploads will not be added to the library view.
+ // this has been traced back to the wp.media.model.Query initialize function (which can't be overriden)
+ // Adding any custom args will cause the Attahcments to not observe the uploader queue
+ // To bypass this security issue, we add in the args AFTER the Query has been initialized
+ // options.library._acfuploader = settings.field;
+ if( this.get('field') && acf.isset(Query, 'mirroring', 'args') ) {
+ Query.mirroring.args._acfuploader = this.get('field');
+ }
+
+ // add states
+ options.states.push(
+
+ // main state
+ new wp.media.controller.Library({
+ library: Query,
+ multiple: this.get('multiple'),
+ title: this.get('title'),
+ priority: 20,
+ filterable: 'all',
+ editable: true,
+ allowLocalEdits: true
+ })
+
+ );
+
+ // edit image functionality (added in WP 3.9)
+ if( acf.isset(wp, 'media', 'controller', 'EditImage') ) {
+ options.states.push( new wp.media.controller.EditImage() );
+ }
+ },
+
+ addFrameEvents: function( frame, options ){
+
+ // log all events
+ //frame.on('all', function( e ) {
+ // console.log( 'frame all: %o', e );
+ //});
+
+ // add class
+ frame.on('open',function() {
+ this.$el.closest('.media-modal').addClass('acf-media-modal -' + this.acf.get('mode') );
+ }, frame);
+
+ // edit image view
+ // source: media-views.js:2410 editImageContent()
+ frame.on('content:render:edit-image', function(){
+
+ var image = this.state().get('image');
+ var view = new wp.media.view.EditImage({ model: image, controller: this }).render();
+ this.content.set( view );
+
+ // after creating the wrapper view, load the actual editor via an ajax call
+ view.loadEditor();
+
+ }, frame);
+
+ // update toolbar button
+ //frame.on( 'toolbar:create:select', function( toolbar ) {
+ // toolbar.view = new wp.media.view.Toolbar.Select({
+ // text: frame.options._button,
+ // controller: this
+ // });
+ //}, frame );
+
+ // on select
+ frame.on('select', function() {
+
+ // vars
+ var selection = frame.state().get('selection');
+
+ // if selecting images
+ if( selection ) {
+
+ // loop
+ selection.each(function( attachment, i ){
+ frame.acf.get('select').apply( frame.acf, [attachment, i] );
+ });
+ }
+ });
+
+ // on close
+ frame.on('close',function(){
+
+ // callback and remove
+ setTimeout(function(){
+ frame.acf.get('close').apply( frame.acf );
+ frame.acf.remove();
+ }, 1);
+ });
+ }
+ });
+
+
+ /**
+ * acf.models.SelectMediaPopup
+ *
+ * description
+ *
+ * @date 10/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.models.SelectMediaPopup = MediaPopup.extend({
+ id: 'SelectMediaPopup',
+ setup: function( props ){
+
+ // default button
+ if( !props.button ) {
+ props.button = acf._x('Select', 'verb');
+ }
+
+ // parent
+ MediaPopup.prototype.setup.apply(this, arguments);
+ },
+
+ addFrameEvents: function( frame, options ){
+
+ // plupload
+ // adds _acfuploader param to validate uploads
+ if( acf.isset(_wpPluploadSettings, 'defaults', 'multipart_params') ) {
+
+ // add _acfuploader so that Uploader will inherit
+ _wpPluploadSettings.defaults.multipart_params._acfuploader = this.get('field');
+
+ // remove acf_field so future Uploaders won't inherit
+ frame.on('open', function(){
+ delete _wpPluploadSettings.defaults.multipart_params._acfuploader;
+ });
+ }
+
+ // browse
+ frame.on('content:activate:browse', function(){
+
+ // vars
+ var toolbar = false;
+
+ // populate above vars making sure to allow for failure
+ // perhaps toolbar does not exist because the frame open is Upload Files
+ try {
+ toolbar = frame.content.get().toolbar;
+ } catch(e) {
+ console.log(e);
+ return;
+ }
+
+ // callback
+ frame.acf.customizeFilters.apply(frame.acf, [toolbar]);
+ });
+
+ // parent
+ MediaPopup.prototype.addFrameEvents.apply(this, arguments);
+
+ },
+
+ customizeFilters: function( toolbar ){
+
+ // vars
+ var filters = toolbar.get('filters');
+
+ // image
+ if( this.get('type') == 'image' ) {
+
+ // update all
+ filters.filters.all.text = acf.__('All images');
+
+ // remove some filters
+ delete filters.filters.audio;
+ delete filters.filters.video;
+ delete filters.filters.image;
+
+ // update all filters to show images
+ $.each(filters.filters, function( i, filter ){
+ filter.props.type = filter.props.type || 'image';
+ });
+ }
+
+ // specific types
+ if( this.get('allowedTypes') ) {
+
+ // convert ".jpg, .png" into ["jpg", "png"]
+ var allowedTypes = this.get('allowedTypes').split(' ').join('').split('.').join('').split(',');
+
+ // loop
+ allowedTypes.map(function( name ){
+
+ // get type
+ var mimeType = acf.getMimeType( name );
+
+ // bail early if no type
+ if( !mimeType ) return;
+
+ // create new filter
+ var newFilter = {
+ text: mimeType,
+ props: {
+ status: null,
+ type: mimeType,
+ uploadedTo: null,
+ orderby: 'date',
+ order: 'DESC'
+ },
+ priority: 20
+ };
+
+ // append
+ filters.filters[ mimeType ] = newFilter;
+
+ });
+ }
+
+
+
+ // uploaded to post
+ if( this.get('library') === 'uploadedTo' ) {
+
+ // vars
+ var uploadedTo = this.frame.options.library.uploadedTo;
+
+ // remove some filters
+ delete filters.filters.unattached;
+ delete filters.filters.uploaded;
+
+ // add uploadedTo to filters
+ $.each(filters.filters, function( i, filter ){
+ filter.text += ' (' + acf.__('Uploaded to this post') + ')';
+ filter.props.uploadedTo = uploadedTo;
+ });
+ }
+
+ // add _acfuploader to filters
+ var field = this.get('field');
+ $.each(filters.filters, function( k, filter ){
+ filter.props._acfuploader = field;
+ });
+
+ // add _acfuplaoder to search
+ var search = toolbar.get('search');
+ search.model.attributes._acfuploader = field;
+
+ // render (custom function added to prototype)
+ if( filters.renderFilters ) {
+ filters.renderFilters();
+ }
+ }
+ });
+
+
+ /**
+ * acf.models.EditMediaPopup
+ *
+ * description
+ *
+ * @date 10/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.models.EditMediaPopup = MediaPopup.extend({
+ id: 'SelectMediaPopup',
+ setup: function( props ){
+
+ // default button
+ if( !props.button ) {
+ props.button = acf._x('Update', 'verb');
+ }
+
+ // parent
+ MediaPopup.prototype.setup.apply(this, arguments);
+ },
+
+ addFrameEvents: function( frame, options ){
+
+ // add class
+ frame.on('open',function() {
+
+ // add class
+ this.$el.closest('.media-modal').addClass('acf-expanded');
+
+ // set to browse
+ if( this.content.mode() != 'browse' ) {
+ this.content.mode('browse');
+ }
+
+ // set selection
+ var state = this.state();
+ var selection = state.get('selection');
+ var attachment = wp.media.attachment( frame.acf.get('attachment') );
+ selection.add( attachment );
+
+ }, frame);
+
+ // parent
+ MediaPopup.prototype.addFrameEvents.apply(this, arguments);
+
+ }
+ });
+
+
+ /**
+ * customizePrototypes
+ *
+ * description
+ *
+ * @date 11/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var customizePrototypes = new acf.Model({
+ id: 'customizePrototypes',
+ wait: 'ready',
+
+ initialize: function(){
+
+ // bail early if no media views
+ if( !acf.isset(window, 'wp', 'media', 'view') ) {
+ return;
+ }
+
+ // fix bug where CPT without "editor" does not set post.id setting which then prevents uploadedTo from working
+ var postID = getPostID();
+ if( postID && acf.isset(wp, 'media', 'view', 'settings', 'post') ) {
+ wp.media.view.settings.post.id = postID;
+ }
+
+ // customize
+ this.customizeAttachmentsButton();
+ this.customizeAttachmentsRouter();
+ this.customizeAttachmentFilters();
+ this.customizeAttachmentCompat();
+ this.customizeAttachmentLibrary();
+ },
+
+ customizeAttachmentsButton: function(){
+
+ // validate
+ if( !acf.isset(wp, 'media', 'view', 'Button') ) {
+ return;
+ }
+
+ // Extend
+ var Button = wp.media.view.Button;
+ wp.media.view.Button = Button.extend({
+
+ // Fix bug where "Select" button appears blank after editing an image.
+ // Do this by simplifying Button initialize function and avoid deleting this.options.
+ initialize: function() {
+ var options = _.defaults( this.options, this.defaults );
+ this.model = new Backbone.Model( options );
+ this.listenTo( this.model, 'change', this.render );
+ }
+ });
+
+ },
+
+ customizeAttachmentsRouter: function(){
+
+ // validate
+ if( !acf.isset(wp, 'media', 'view', 'Router') ) {
+ return;
+ }
+
+ // vars
+ var Parent = wp.media.view.Router;
+
+ // extend
+ wp.media.view.Router = Parent.extend({
+
+ addExpand: function(){
+
+ // vars
+ var $a = $([
+ '',
+ ' ' + acf.__('Expand Details') + ' ',
+ ' ' + acf.__('Collapse Details') + ' ',
+ ' '
+ ].join(''));
+
+ // add events
+ $a.on('click', function( e ){
+ e.preventDefault();
+ var $div = $(this).closest('.media-modal');
+ if( $div.hasClass('acf-expanded') ) {
+ $div.removeClass('acf-expanded');
+ } else {
+ $div.addClass('acf-expanded');
+ }
+ });
+
+ // append
+ this.$el.append( $a );
+ },
+
+ initialize: function(){
+
+ // initialize
+ Parent.prototype.initialize.apply( this, arguments );
+
+ // add buttons
+ this.addExpand();
+
+ // return
+ return this;
+ }
+ });
+ },
+
+ customizeAttachmentFilters: function(){
+
+ // validate
+ if( !acf.isset(wp, 'media', 'view', 'AttachmentFilters', 'All') ) {
+ return;
+ }
+
+ // vars
+ var Parent = wp.media.view.AttachmentFilters.All;
+
+ // renderFilters
+ // copied from media-views.js:6939
+ Parent.prototype.renderFilters = function(){
+
+ // Build `` elements.
+ this.$el.html( _.chain( this.filters ).map( function( filter, value ) {
+ return {
+ el: $( ' ' ).val( value ).html( filter.text )[0],
+ priority: filter.priority || 50
+ };
+ }, this ).sortBy('priority').pluck('el').value() );
+
+ };
+ },
+
+ customizeAttachmentCompat: function(){
+
+ // validate
+ if( !acf.isset(wp, 'media', 'view', 'AttachmentCompat') ) {
+ return;
+ }
+
+ // vars
+ var AttachmentCompat = wp.media.view.AttachmentCompat;
+ var timeout = false;
+
+ // extend
+ wp.media.view.AttachmentCompat = AttachmentCompat.extend({
+
+ render: function() {
+
+ // WP bug
+ // When multiple media frames exist on the same page (WP content, WYSIWYG, image, file ),
+ // WP creates multiple instances of this AttachmentCompat view.
+ // Each instance will attempt to render when a new modal is created.
+ // Use a property to avoid this and only render once per instance.
+ if( this.rendered ) {
+ return this;
+ }
+
+ // render HTML
+ AttachmentCompat.prototype.render.apply( this, arguments );
+
+ // when uploading, render is called twice.
+ // ignore first render by checking for #acf-form-data element
+ if( !this.$('#acf-form-data').length ) {
+ return this;
+ }
+
+ // clear timeout
+ clearTimeout( timeout );
+
+ // setTimeout
+ timeout = setTimeout($.proxy(function(){
+ this.rendered = true;
+ acf.doAction('append', this.$el);
+ }, this), 50);
+
+ // return
+ return this;
+ },
+
+ save: function( event ) {
+ var data = {};
+
+ if ( event ) {
+ event.preventDefault();
+ }
+
+ //_.each( this.$el.serializeArray(), function( pair ) {
+ // data[ pair.name ] = pair.value;
+ //});
+
+ // Serialize data more thoroughly to allow chckbox inputs to save.
+ data = acf.serializeForAjax(this.$el);
+
+ this.controller.trigger( 'attachment:compat:waiting', ['waiting'] );
+ this.model.saveCompat( data ).always( _.bind( this.postSave, this ) );
+ }
+ });
+
+ },
+
+ customizeAttachmentLibrary: function(){
+
+ // validate
+ if( !acf.isset(wp, 'media', 'view', 'Attachment', 'Library') ) {
+ return;
+ }
+
+ // vars
+ var AttachmentLibrary = wp.media.view.Attachment.Library;
+
+ // extend
+ wp.media.view.Attachment.Library = AttachmentLibrary.extend({
+
+ render: function() {
+
+ // vars
+ var popup = acf.isget(this, 'controller', 'acf');
+ var attributes = acf.isget(this, 'model', 'attributes');
+
+ // check vars exist to avoid errors
+ if( popup && attributes ) {
+
+ // show errors
+ if( attributes.acf_errors ) {
+ this.$el.addClass('acf-disabled');
+ }
+
+ // disable selected
+ var selected = popup.get('selected');
+ if( selected && selected.indexOf(attributes.id) > -1 ) {
+ this.$el.addClass('acf-selected');
+ }
+ }
+
+ // render
+ return AttachmentLibrary.prototype.render.apply( this, arguments );
+
+ },
+
+
+ /*
+ * toggleSelection
+ *
+ * This function is called before an attachment is selected
+ * A good place to check for errors and prevent the 'select' function from being fired
+ *
+ * @type function
+ * @date 29/09/2016
+ * @since 5.4.0
+ *
+ * @param options (object)
+ * @return n/a
+ */
+
+ toggleSelection: function( options ) {
+
+ // vars
+ // source: wp-includes/js/media-views.js:2880
+ var collection = this.collection,
+ selection = this.options.selection,
+ model = this.model,
+ single = selection.single();
+
+
+ // vars
+ var frame = this.controller;
+ var errors = acf.isget(this, 'model', 'attributes', 'acf_errors');
+ var $sidebar = frame.$el.find('.media-frame-content .media-sidebar');
+
+ // remove previous error
+ $sidebar.children('.acf-selection-error').remove();
+
+ // show attachment details
+ $sidebar.children().removeClass('acf-hidden');
+
+ // add message
+ if( frame && errors ) {
+
+ // vars
+ var filename = acf.isget(this, 'model', 'attributes', 'filename');
+
+ // hide attachment details
+ // Gallery field continues to show previously selected attachment...
+ $sidebar.children().addClass('acf-hidden');
+
+ // append message
+ $sidebar.prepend([
+ '',
+ '' + acf.__('Restricted') +' ',
+ '' + filename + ' ',
+ '' + errors + ' ',
+ '
'
+ ].join(''));
+
+ // reset selection (unselects all attachments)
+ selection.reset();
+
+ // set single (attachment displayed in sidebar)
+ selection.single( model );
+
+ // return and prevent 'select' form being fired
+ return;
+
+ }
+
+ // return
+ return AttachmentLibrary.prototype.toggleSelection.apply( this, arguments );
+ }
+ });
+ }
+ });
-(function ($, undefined) {
- /**
- * acf.newMediaPopup
- *
- * description
- *
- * @date 10/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- acf.newMediaPopup = function (args) {
- // args
- var popup = null;
- var args = acf.parseArgs(args, {
- mode: 'select',
- // 'select', 'edit'
- title: '',
- // 'Upload Image'
- button: '',
- // 'Select Image'
- type: '',
- // 'image', ''
- field: false,
- // field instance
- allowedTypes: '',
- // '.jpg, .png, etc'
- library: 'all',
- // 'all', 'uploadedTo'
- multiple: false,
- // false, true, 'add'
- attachment: 0,
- // the attachment to edit
- autoOpen: true,
- // open the popup automatically
- open: function () {},
- // callback after close
- select: function () {},
- // callback after select
- close: function () {} // callback after close
-
- }); // initialize
-
- if (args.mode == 'edit') {
- popup = new acf.models.EditMediaPopup(args);
- } else {
- popup = new acf.models.SelectMediaPopup(args);
- } // open popup (allow frame customization before opening)
-
-
- if (args.autoOpen) {
- setTimeout(function () {
- popup.open();
- }, 1);
- } // action
-
-
- acf.doAction('new_media_popup', popup); // return
-
- return popup;
- };
- /**
- * getPostID
- *
- * description
- *
- * @date 10/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- var getPostID = function () {
- var postID = acf.get('post_id');
- return acf.isNumeric(postID) ? postID : 0;
- };
- /**
- * acf.getMimeTypes
- *
- * description
- *
- * @date 11/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- acf.getMimeTypes = function () {
- return this.get('mimeTypes');
- };
-
- acf.getMimeType = function (name) {
- // vars
- var allTypes = acf.getMimeTypes(); // search
-
- if (allTypes[name] !== undefined) {
- return allTypes[name];
- } // some types contain a mixed key such as "jpg|jpeg|jpe"
-
-
- for (var key in allTypes) {
- if (key.indexOf(name) !== -1) {
- return allTypes[key];
- }
- } // return
-
-
- return false;
- };
- /**
- * MediaPopup
- *
- * description
- *
- * @date 10/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- var MediaPopup = acf.Model.extend({
- id: 'MediaPopup',
- data: {},
- defaults: {},
- frame: false,
- setup: function (props) {
- $.extend(this.data, props);
- },
- initialize: function () {
- // vars
- var options = this.getFrameOptions(); // add states
-
- this.addFrameStates(options); // create frame
-
- var frame = wp.media(options); // add args reference
-
- frame.acf = this; // add events
-
- this.addFrameEvents(frame, options); // strore frame
-
- this.frame = frame;
- },
- open: function () {
- this.frame.open();
- },
- close: function () {
- this.frame.close();
- },
- remove: function () {
- this.frame.detach();
- this.frame.remove();
- },
- getFrameOptions: function () {
- // vars
- var options = {
- title: this.get('title'),
- multiple: this.get('multiple'),
- library: {},
- states: []
- }; // type
-
- if (this.get('type')) {
- options.library.type = this.get('type');
- } // type
-
-
- if (this.get('library') === 'uploadedTo') {
- options.library.uploadedTo = getPostID();
- } // attachment
-
-
- if (this.get('attachment')) {
- options.library.post__in = [this.get('attachment')];
- } // button
-
-
- if (this.get('button')) {
- options.button = {
- text: this.get('button')
- };
- } // return
-
-
- return options;
- },
- addFrameStates: function (options) {
- // create query
- var Query = wp.media.query(options.library); // add _acfuploader
- // this is super wack!
- // if you add _acfuploader to the options.library args, new uploads will not be added to the library view.
- // this has been traced back to the wp.media.model.Query initialize function (which can't be overriden)
- // Adding any custom args will cause the Attahcments to not observe the uploader queue
- // To bypass this security issue, we add in the args AFTER the Query has been initialized
- // options.library._acfuploader = settings.field;
-
- if (this.get('field') && acf.isset(Query, 'mirroring', 'args')) {
- Query.mirroring.args._acfuploader = this.get('field');
- } // add states
-
-
- options.states.push( // main state
- new wp.media.controller.Library({
- library: Query,
- multiple: this.get('multiple'),
- title: this.get('title'),
- priority: 20,
- filterable: 'all',
- editable: true,
- allowLocalEdits: true
- })); // edit image functionality (added in WP 3.9)
-
- if (acf.isset(wp, 'media', 'controller', 'EditImage')) {
- options.states.push(new wp.media.controller.EditImage());
- }
- },
- addFrameEvents: function (frame, options) {
- // log all events
- //frame.on('all', function( e ) {
- // console.log( 'frame all: %o', e );
- //});
- // add class
- frame.on('open', function () {
- this.$el.closest('.media-modal').addClass('acf-media-modal -' + this.acf.get('mode'));
- }, frame); // edit image view
- // source: media-views.js:2410 editImageContent()
-
- frame.on('content:render:edit-image', function () {
- var image = this.state().get('image');
- var view = new wp.media.view.EditImage({
- model: image,
- controller: this
- }).render();
- this.content.set(view); // after creating the wrapper view, load the actual editor via an ajax call
-
- view.loadEditor();
- }, frame); // update toolbar button
- //frame.on( 'toolbar:create:select', function( toolbar ) {
- // toolbar.view = new wp.media.view.Toolbar.Select({
- // text: frame.options._button,
- // controller: this
- // });
- //}, frame );
- // on select
-
- frame.on('select', function () {
- // vars
- var selection = frame.state().get('selection'); // if selecting images
-
- if (selection) {
- // loop
- selection.each(function (attachment, i) {
- frame.acf.get('select').apply(frame.acf, [attachment, i]);
- });
- }
- }); // on close
-
- frame.on('close', function () {
- // callback and remove
- setTimeout(function () {
- frame.acf.get('close').apply(frame.acf);
- frame.acf.remove();
- }, 1);
- });
- }
- });
- /**
- * acf.models.SelectMediaPopup
- *
- * description
- *
- * @date 10/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.models.SelectMediaPopup = MediaPopup.extend({
- id: 'SelectMediaPopup',
- setup: function (props) {
- // default button
- if (!props.button) {
- props.button = acf._x('Select', 'verb');
- } // parent
-
-
- MediaPopup.prototype.setup.apply(this, arguments);
- },
- addFrameEvents: function (frame, options) {
- // plupload
- // adds _acfuploader param to validate uploads
- if (acf.isset(_wpPluploadSettings, 'defaults', 'multipart_params')) {
- // add _acfuploader so that Uploader will inherit
- _wpPluploadSettings.defaults.multipart_params._acfuploader = this.get('field'); // remove acf_field so future Uploaders won't inherit
-
- frame.on('open', function () {
- delete _wpPluploadSettings.defaults.multipart_params._acfuploader;
- });
- } // browse
-
-
- frame.on('content:activate:browse', function () {
- // vars
- var toolbar = false; // populate above vars making sure to allow for failure
- // perhaps toolbar does not exist because the frame open is Upload Files
-
- try {
- toolbar = frame.content.get().toolbar;
- } catch (e) {
- console.log(e);
- return;
- } // callback
-
-
- frame.acf.customizeFilters.apply(frame.acf, [toolbar]);
- }); // parent
-
- MediaPopup.prototype.addFrameEvents.apply(this, arguments);
- },
- customizeFilters: function (toolbar) {
- // vars
- var filters = toolbar.get('filters'); // image
-
- if (this.get('type') == 'image') {
- // update all
- filters.filters.all.text = acf.__('All images'); // remove some filters
-
- delete filters.filters.audio;
- delete filters.filters.video;
- delete filters.filters.image; // update all filters to show images
-
- $.each(filters.filters, function (i, filter) {
- filter.props.type = filter.props.type || 'image';
- });
- } // specific types
-
-
- if (this.get('allowedTypes')) {
- // convert ".jpg, .png" into ["jpg", "png"]
- var allowedTypes = this.get('allowedTypes').split(' ').join('').split('.').join('').split(','); // loop
-
- allowedTypes.map(function (name) {
- // get type
- var mimeType = acf.getMimeType(name); // bail early if no type
-
- if (!mimeType) return; // create new filter
-
- var newFilter = {
- text: mimeType,
- props: {
- status: null,
- type: mimeType,
- uploadedTo: null,
- orderby: 'date',
- order: 'DESC'
- },
- priority: 20
- }; // append
-
- filters.filters[mimeType] = newFilter;
- });
- } // uploaded to post
-
-
- if (this.get('library') === 'uploadedTo') {
- // vars
- var uploadedTo = this.frame.options.library.uploadedTo; // remove some filters
-
- delete filters.filters.unattached;
- delete filters.filters.uploaded; // add uploadedTo to filters
-
- $.each(filters.filters, function (i, filter) {
- filter.text += ' (' + acf.__('Uploaded to this post') + ')';
- filter.props.uploadedTo = uploadedTo;
- });
- } // add _acfuploader to filters
-
-
- var field = this.get('field');
- $.each(filters.filters, function (k, filter) {
- filter.props._acfuploader = field;
- }); // add _acfuplaoder to search
-
- var search = toolbar.get('search');
- search.model.attributes._acfuploader = field; // render (custom function added to prototype)
-
- if (filters.renderFilters) {
- filters.renderFilters();
- }
- }
- });
- /**
- * acf.models.EditMediaPopup
- *
- * description
- *
- * @date 10/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.models.EditMediaPopup = MediaPopup.extend({
- id: 'SelectMediaPopup',
- setup: function (props) {
- // default button
- if (!props.button) {
- props.button = acf._x('Update', 'verb');
- } // parent
-
-
- MediaPopup.prototype.setup.apply(this, arguments);
- },
- addFrameEvents: function (frame, options) {
- // add class
- frame.on('open', function () {
- // add class
- this.$el.closest('.media-modal').addClass('acf-expanded'); // set to browse
-
- if (this.content.mode() != 'browse') {
- this.content.mode('browse');
- } // set selection
-
-
- var state = this.state();
- var selection = state.get('selection');
- var attachment = wp.media.attachment(frame.acf.get('attachment'));
- selection.add(attachment);
- }, frame); // parent
-
- MediaPopup.prototype.addFrameEvents.apply(this, arguments);
- }
- });
- /**
- * customizePrototypes
- *
- * description
- *
- * @date 11/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var customizePrototypes = new acf.Model({
- id: 'customizePrototypes',
- wait: 'ready',
- initialize: function () {
- // bail early if no media views
- if (!acf.isset(window, 'wp', 'media', 'view')) {
- return;
- } // fix bug where CPT without "editor" does not set post.id setting which then prevents uploadedTo from working
-
-
- var postID = getPostID();
-
- if (postID && acf.isset(wp, 'media', 'view', 'settings', 'post')) {
- wp.media.view.settings.post.id = postID;
- } // customize
-
-
- this.customizeAttachmentsButton();
- this.customizeAttachmentsRouter();
- this.customizeAttachmentFilters();
- this.customizeAttachmentCompat();
- this.customizeAttachmentLibrary();
- },
- customizeAttachmentsButton: function () {
- // validate
- if (!acf.isset(wp, 'media', 'view', 'Button')) {
- return;
- } // Extend
-
-
- var Button = wp.media.view.Button;
- wp.media.view.Button = Button.extend({
- // Fix bug where "Select" button appears blank after editing an image.
- // Do this by simplifying Button initialize function and avoid deleting this.options.
- initialize: function () {
- var options = _.defaults(this.options, this.defaults);
-
- this.model = new Backbone.Model(options);
- this.listenTo(this.model, 'change', this.render);
- }
- });
- },
- customizeAttachmentsRouter: function () {
- // validate
- if (!acf.isset(wp, 'media', 'view', 'Router')) {
- return;
- } // vars
-
-
- var Parent = wp.media.view.Router; // extend
-
- wp.media.view.Router = Parent.extend({
- addExpand: function () {
- // vars
- var $a = $(['', ' ' + acf.__('Expand Details') + ' ', ' ' + acf.__('Collapse Details') + ' ', ' '].join('')); // add events
-
- $a.on('click', function (e) {
- e.preventDefault();
- var $div = $(this).closest('.media-modal');
-
- if ($div.hasClass('acf-expanded')) {
- $div.removeClass('acf-expanded');
- } else {
- $div.addClass('acf-expanded');
- }
- }); // append
-
- this.$el.append($a);
- },
- initialize: function () {
- // initialize
- Parent.prototype.initialize.apply(this, arguments); // add buttons
-
- this.addExpand(); // return
-
- return this;
- }
- });
- },
- customizeAttachmentFilters: function () {
- // validate
- if (!acf.isset(wp, 'media', 'view', 'AttachmentFilters', 'All')) {
- return;
- } // vars
-
-
- var Parent = wp.media.view.AttachmentFilters.All; // renderFilters
- // copied from media-views.js:6939
-
- Parent.prototype.renderFilters = function () {
- // Build `` elements.
- this.$el.html(_.chain(this.filters).map(function (filter, value) {
- return {
- el: $(' ').val(value).html(filter.text)[0],
- priority: filter.priority || 50
- };
- }, this).sortBy('priority').pluck('el').value());
- };
- },
- customizeAttachmentCompat: function () {
- // validate
- if (!acf.isset(wp, 'media', 'view', 'AttachmentCompat')) {
- return;
- } // vars
-
-
- var AttachmentCompat = wp.media.view.AttachmentCompat;
- var timeout = false; // extend
-
- wp.media.view.AttachmentCompat = AttachmentCompat.extend({
- render: function () {
- // WP bug
- // When multiple media frames exist on the same page (WP content, WYSIWYG, image, file ),
- // WP creates multiple instances of this AttachmentCompat view.
- // Each instance will attempt to render when a new modal is created.
- // Use a property to avoid this and only render once per instance.
- if (this.rendered) {
- return this;
- } // render HTML
-
-
- AttachmentCompat.prototype.render.apply(this, arguments); // when uploading, render is called twice.
- // ignore first render by checking for #acf-form-data element
-
- if (!this.$('#acf-form-data').length) {
- return this;
- } // clear timeout
-
-
- clearTimeout(timeout); // setTimeout
-
- timeout = setTimeout($.proxy(function () {
- this.rendered = true;
- acf.doAction('append', this.$el);
- }, this), 50); // return
-
- return this;
- },
- save: function (event) {
- var data = {};
-
- if (event) {
- event.preventDefault();
- } //_.each( this.$el.serializeArray(), function( pair ) {
- // data[ pair.name ] = pair.value;
- //});
- // Serialize data more thoroughly to allow chckbox inputs to save.
-
-
- data = acf.serializeForAjax(this.$el);
- this.controller.trigger('attachment:compat:waiting', ['waiting']);
- this.model.saveCompat(data).always(_.bind(this.postSave, this));
- }
- });
- },
- customizeAttachmentLibrary: function () {
- // validate
- if (!acf.isset(wp, 'media', 'view', 'Attachment', 'Library')) {
- return;
- } // vars
-
-
- var AttachmentLibrary = wp.media.view.Attachment.Library; // extend
-
- wp.media.view.Attachment.Library = AttachmentLibrary.extend({
- render: function () {
- // vars
- var popup = acf.isget(this, 'controller', 'acf');
- var attributes = acf.isget(this, 'model', 'attributes'); // check vars exist to avoid errors
-
- if (popup && attributes) {
- // show errors
- if (attributes.acf_errors) {
- this.$el.addClass('acf-disabled');
- } // disable selected
-
-
- var selected = popup.get('selected');
-
- if (selected && selected.indexOf(attributes.id) > -1) {
- this.$el.addClass('acf-selected');
- }
- } // render
-
-
- return AttachmentLibrary.prototype.render.apply(this, arguments);
- },
-
- /*
- * toggleSelection
- *
- * This function is called before an attachment is selected
- * A good place to check for errors and prevent the 'select' function from being fired
- *
- * @type function
- * @date 29/09/2016
- * @since 5.4.0
- *
- * @param options (object)
- * @return n/a
- */
- toggleSelection: function (options) {
- // vars
- // source: wp-includes/js/media-views.js:2880
- var collection = this.collection,
- selection = this.options.selection,
- model = this.model,
- single = selection.single(); // vars
-
- var frame = this.controller;
- var errors = acf.isget(this, 'model', 'attributes', 'acf_errors');
- var $sidebar = frame.$el.find('.media-frame-content .media-sidebar'); // remove previous error
-
- $sidebar.children('.acf-selection-error').remove(); // show attachment details
-
- $sidebar.children().removeClass('acf-hidden'); // add message
-
- if (frame && errors) {
- // vars
- var filename = acf.isget(this, 'model', 'attributes', 'filename'); // hide attachment details
- // Gallery field continues to show previously selected attachment...
-
- $sidebar.children().addClass('acf-hidden'); // append message
-
- $sidebar.prepend(['', '' + acf.__('Restricted') + ' ', '' + filename + ' ', '' + errors + ' ', '
'].join('')); // reset selection (unselects all attachments)
-
- selection.reset(); // set single (attachment displayed in sidebar)
-
- selection.single(model); // return and prevent 'select' form being fired
-
- return;
- } // return
-
-
- return AttachmentLibrary.prototype.toggleSelection.apply(this, arguments);
- }
- });
- }
- });
})(jQuery);
+(function($, undefined){
+
+ acf.screen = new acf.Model({
+
+ active: true,
+
+ xhr: false,
+
+ timeout: false,
+
+ wait: 'load',
+
+ events: {
+ 'change #page_template': 'onChange',
+ 'change #parent_id': 'onChange',
+ 'change #post-formats-select': 'onChange',
+ 'change .categorychecklist': 'onChange',
+ 'change .tagsdiv': 'onChange',
+ 'change .acf-taxonomy-field[data-save="1"]': 'onChange',
+ 'change #product-type': 'onChange'
+ },
+
+ isPost: function(){
+ return acf.get('screen') === 'post';
+ },
+
+ isUser: function(){
+ return acf.get('screen') === 'user';
+ },
+
+ isTaxonomy: function(){
+ return acf.get('screen') === 'taxonomy';
+ },
+
+ isAttachment: function(){
+ return acf.get('screen') === 'attachment';
+ },
+
+ isNavMenu: function(){
+ return acf.get('screen') === 'nav_menu';
+ },
+
+ isWidget: function(){
+ return acf.get('screen') === 'widget';
+ },
+
+ isComment: function(){
+ return acf.get('screen') === 'comment';
+ },
+
+ getPageTemplate: function(){
+ var $el = $('#page_template');
+ return $el.length ? $el.val() : null;
+ },
+
+ getPageParent: function( e, $el ){
+ var $el = $('#parent_id');
+ return $el.length ? $el.val() : null;
+ },
+
+ getPageType: function( e, $el ){
+ return this.getPageParent() ? 'child' : 'parent';
+ },
+
+ getPostType: function(){
+ return $('#post_type').val();
+ },
+
+ getPostFormat: function( e, $el ){
+ var $el = $('#post-formats-select input:checked');
+ if( $el.length ) {
+ var val = $el.val();
+ return (val == '0') ? 'standard' : val;
+ }
+ return null;
+ },
+
+ getPostCoreTerms: function(){
+
+ // vars
+ var terms = {};
+
+ // serialize WP taxonomy postboxes
+ var data = acf.serialize( $('.categorydiv, .tagsdiv') );
+
+ // use tax_input (tag, custom-taxonomy) when possible.
+ // this data is already formatted in taxonomy => [terms].
+ if( data.tax_input ) {
+ terms = data.tax_input;
+ }
+
+ // append "category" which uses a different name
+ if( data.post_category ) {
+ terms.category = data.post_category;
+ }
+
+ // convert any string values (tags) into array format
+ for( var tax in terms ) {
+ if( !acf.isArray(terms[tax]) ) {
+ terms[tax] = terms[tax].split(/,[\s]?/);
+ }
+ }
+
+ // return
+ return terms;
+ },
+
+ getPostTerms: function(){
+
+ // Get core terms.
+ var terms = this.getPostCoreTerms();
+
+ // loop over taxonomy fields and add their values
+ acf.getFields({type: 'taxonomy'}).map(function( field ){
+
+ // ignore fields that don't save
+ if( !field.get('save') ) {
+ return;
+ }
+
+ // vars
+ var val = field.val();
+ var tax = field.get('taxonomy');
+
+ // check val
+ if( val ) {
+
+ // ensure terms exists
+ terms[ tax ] = terms[ tax ] || [];
+
+ // ensure val is an array
+ val = acf.isArray(val) ? val : [val];
+
+ // append
+ terms[ tax ] = terms[ tax ].concat( val );
+ }
+ });
+
+ // add WC product type
+ if( (productType = this.getProductType()) !== null ) {
+ terms.product_type = [productType];
+ }
+
+ // remove duplicate values
+ for( var tax in terms ) {
+ terms[tax] = acf.uniqueArray(terms[tax]);
+ }
+
+ // return
+ return terms;
+ },
+
+ getProductType: function(){
+ var $el = $('#product-type');
+ return $el.length ? $el.val() : null;
+ },
+
+ check: function(){
+
+ // bail early if not for post
+ if( acf.get('screen') !== 'post' ) {
+ return;
+ }
+
+ // abort XHR if is already loading AJAX data
+ if( this.xhr ) {
+ this.xhr.abort();
+ }
+
+ // vars
+ var ajaxData = acf.parseArgs(this.data, {
+ action: 'acf/ajax/check_screen',
+ screen: acf.get('screen'),
+ exists: []
+ });
+
+ // post id
+ if( this.isPost() ) {
+ ajaxData.post_id = acf.get('post_id');
+ }
+
+ // post type
+ if( (postType = this.getPostType()) !== null ) {
+ ajaxData.post_type = postType;
+ }
+
+ // page template
+ if( (pageTemplate = this.getPageTemplate()) !== null ) {
+ ajaxData.page_template = pageTemplate;
+ }
+
+ // page parent
+ if( (pageParent = this.getPageParent()) !== null ) {
+ ajaxData.page_parent = pageParent;
+ }
+
+ // page type
+ if( (pageType = this.getPageType()) !== null ) {
+ ajaxData.page_type = pageType;
+ }
+
+ // post format
+ if( (postFormat = this.getPostFormat()) !== null ) {
+ ajaxData.post_format = postFormat;
+ }
+
+ // post terms
+ if( (postTerms = this.getPostTerms()) !== null ) {
+ ajaxData.post_terms = postTerms;
+ }
+
+ // add array of existing postboxes to increase performance and reduce JSON HTML
+ acf.getPostboxes().map(function( postbox ){
+ ajaxData.exists.push( postbox.get('key') );
+ });
+
+ // filter
+ ajaxData = acf.applyFilters('check_screen_args', ajaxData);
+
+ // success
+ var onSuccess = function( json ){
+
+ // Render post screen.
+ if( acf.get('screen') == 'post' ) {
+ this.renderPostScreen( json );
+
+ // Render user screen.
+ } else if( acf.get('screen') == 'user' ) {
+ this.renderUserScreen( json );
+ }
+
+ // action
+ acf.doAction('check_screen_complete', json, ajaxData);
+ };
+
+ // ajax
+ this.xhr = $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax( ajaxData ),
+ type: 'post',
+ dataType: 'json',
+ context: this,
+ success: onSuccess
+ });
+ },
+
+ onChange: function( e, $el ){
+ this.setTimeout(this.check, 1);
+ },
+
+ renderPostScreen: function( data ){
+
+ // Helper function to copy events
+ var copyEvents = function( $from, $to ){
+ var events = $._data($from[0]).events;
+ for( var type in events ) {
+ for( var i = 0; i < events[type].length; i++ ) {
+ $to.on( type, events[type][i].handler );
+ }
+ }
+ }
+
+ // Helper function to sort metabox.
+ var sortMetabox = function( id, ids ){
+
+ // Find position of id within ids.
+ var index = ids.indexOf( id );
+
+ // Bail early if index not found.
+ if( index == -1 ) {
+ return false;
+ }
+
+ // Loop over metaboxes behind (in reverse order).
+ for( var i = index-1; i >= 0; i-- ) {
+ if( $('#'+ids[i]).length ) {
+ return $('#'+ids[i]).after( $('#'+id) );
+ }
+ }
+
+ // Loop over metaboxes infront.
+ for( var i = index+1; i < ids.length; i++ ) {
+ if( $('#'+ids[i]).length ) {
+ return $('#'+ids[i]).before( $('#'+id) );
+ }
+ }
+
+ // Return false if not sorted.
+ return false;
+ };
+
+ // Keep track of visible and hidden postboxes.
+ data.visible = [];
+ data.hidden = [];
+
+ // Show these postboxes.
+ data.results = data.results.map(function( result, i ){
+
+ // vars
+ var postbox = acf.getPostbox( result.id );
+
+ // Prevent "acf_after_title" position in Block Editor.
+ if( acf.isGutenberg() && result.position == "acf_after_title" ) {
+ result.position = 'normal';
+ }
+
+ // Create postbox if doesn't exist.
+ if( !postbox ) {
+ var wpMinorVersion = parseFloat( acf.get('wp_version') );
+ if( wpMinorVersion >= 5.5 ) {
+ var postboxHeader = [
+ ''
+ ].join('');
+ } else {
+ var postboxHeader = [
+ '',
+ 'Toggle panel: ' + acf.escHtml( result.title ) + ' ',
+ ' ',
+ ' ',
+ '',
+ '' + acf.escHtml( result.title ) + ' ',
+ ' ',
+ ].join('');
+ }
+
+ // Create it.
+ var $postbox = $([
+ '',
+ postboxHeader,
+ '
',
+ result.html,
+ '
',
+ '
'
+ ].join(''));
+
+ // Create new hide toggle.
+ if( $('#adv-settings').length ) {
+ var $prefs = $('#adv-settings .metabox-prefs');
+ var $label = $([
+ '',
+ ' ',
+ ' ' + result.title,
+ ' '
+ ].join(''));
+
+ // Copy default WP events onto checkbox.
+ copyEvents( $prefs.find('input').first(), $label.find('input') );
+
+ // Append hide label
+ $prefs.append( $label );
+ }
+
+ // Copy default WP events onto metabox.
+ if( $('.postbox').length ) {
+ copyEvents( $('.postbox .handlediv').first(), $postbox.children('.handlediv') );
+ copyEvents( $('.postbox .hndle').first(), $postbox.children('.hndle') );
+ }
+
+ // Append metabox to the bottom of "side-sortables".
+ if( result.position === 'side' ) {
+ $('#' + result.position + '-sortables').append( $postbox );
+
+ // Prepend metabox to the top of "normal-sortbables".
+ } else {
+ $('#' + result.position + '-sortables').prepend( $postbox );
+ }
+
+ // Position metabox amongst existing ACF metaboxes within the same location.
+ var order = [];
+ data.results.map(function( _result ){
+ if( result.position === _result.position && $('#' + result.position + '-sortables #' + _result.id).length ) {
+ order.push( _result.id );
+ }
+ });
+ sortMetabox(result.id, order)
+
+ // Check 'sorted' for user preference.
+ if( data.sorted ) {
+
+ // Loop over each position (acf_after_title, side, normal).
+ for( var position in data.sorted ) {
+
+ // Explode string into array of ids.
+ var order = data.sorted[position].split(',');
+
+ // Position metabox relative to order.
+ if( sortMetabox(result.id, order) ) {
+ break;
+ }
+ }
+ }
+
+ // Initalize it (modifies HTML).
+ postbox = acf.newPostbox( result );
+
+ // Trigger action.
+ acf.doAction('append', $postbox);
+ acf.doAction('append_postbox', postbox);
+ }
+
+ // show postbox
+ postbox.showEnable();
+
+ // append
+ data.visible.push( result.id );
+
+ // Return result (may have changed).
+ return result;
+ });
+
+ // Hide these postboxes.
+ acf.getPostboxes().map(function( postbox ){
+ if( data.visible.indexOf( postbox.get('id') ) === -1 ) {
+
+ // Hide postbox.
+ postbox.hideDisable();
+
+ // Append to data.
+ data.hidden.push( postbox.get('id') );
+ }
+ });
+
+ // Update style.
+ $('#acf-style').html( data.style );
+
+ // Do action.
+ acf.doAction( 'refresh_post_screen', data );
+ },
+
+ renderUserScreen: function( json ){
+
+ }
+ });
+
+ /**
+ * gutenScreen
+ *
+ * Adds compatibility with the Gutenberg edit screen.
+ *
+ * @date 11/12/18
+ * @since 5.8.0
+ *
+ * @param void
+ * @return void
+ */
+ var gutenScreen = new acf.Model({
+
+ // Keep a reference to the most recent post attributes.
+ postEdits: {},
+
+ // Wait until assets have been loaded.
+ wait: 'prepare',
+
+ initialize: function(){
+
+ // Bail early if not Gutenberg.
+ if( !acf.isGutenberg() ) {
+ return;
+ }
+
+ // Listen for changes (use debounced version as this can fires often).
+ wp.data.subscribe( acf.debounce(this.onChange).bind(this) );
+
+ // Customize "acf.screen.get" functions.
+ acf.screen.getPageTemplate = this.getPageTemplate;
+ acf.screen.getPageParent = this.getPageParent;
+ acf.screen.getPostType = this.getPostType;
+ acf.screen.getPostFormat = this.getPostFormat;
+ acf.screen.getPostCoreTerms = this.getPostCoreTerms;
+
+ // Disable unload
+ acf.unload.disable();
+
+ // Refresh metaboxes since WP 5.3.
+ var wpMinorVersion = parseFloat( acf.get('wp_version') );
+ if( wpMinorVersion >= 5.3 ) {
+ this.addAction( 'refresh_post_screen', this.onRefreshPostScreen );
+ }
+
+ // Trigger "refresh" after WP has moved metaboxes into place.
+ wp.domReady( acf.refresh );
+ },
+
+ onChange: function(){
+
+ // Determine attributes that can trigger a refresh.
+ var attributes = [ 'template', 'parent', 'format' ];
+
+ // Append taxonomy attribute names to this list.
+ ( wp.data.select( 'core' ).getTaxonomies() || [] ).map(function( taxonomy ){
+ attributes.push( taxonomy.rest_base );
+ });
+
+ // Get relevant current post edits.
+ var _postEdits = wp.data.select( 'core/editor' ).getPostEdits();
+ var postEdits = {};
+ attributes.map(function( k ){
+ if( _postEdits[k] !== undefined ) {
+ postEdits[k] = _postEdits[k];
+ }
+ });
+
+ // Detect change.
+ if( JSON.stringify(postEdits) !== JSON.stringify(this.postEdits) ) {
+ this.postEdits = postEdits;
+
+ // Check screen.
+ acf.screen.check();
+ }
+ },
+
+ getPageTemplate: function(){
+ return wp.data.select( 'core/editor' ).getEditedPostAttribute( 'template' );
+ },
+
+ getPageParent: function( e, $el ){
+ return wp.data.select( 'core/editor' ).getEditedPostAttribute( 'parent' );
+ },
+
+ getPostType: function(){
+ return wp.data.select( 'core/editor' ).getEditedPostAttribute( 'type' );
+ },
+
+ getPostFormat: function( e, $el ){
+ return wp.data.select( 'core/editor' ).getEditedPostAttribute( 'format' );
+ },
+
+ getPostCoreTerms: function(){
+
+ // vars
+ var terms = {};
+
+ // Loop over taxonomies.
+ var taxonomies = wp.data.select( 'core' ).getTaxonomies() || [];
+ taxonomies.map(function( taxonomy ){
+
+ // Append selected taxonomies to terms object.
+ var postTerms = wp.data.select( 'core/editor' ).getEditedPostAttribute( taxonomy.rest_base );
+ if( postTerms ) {
+ terms[ taxonomy.slug ] = postTerms;
+ }
+ });
+
+ // return
+ return terms;
+ },
+
+ /**
+ * onRefreshPostScreen
+ *
+ * Fires after the Post edit screen metaboxs are refreshed to update the Block Editor API state.
+ *
+ * @date 11/11/19
+ * @since 5.8.7
+ *
+ * @param object data The "check_screen" JSON response data.
+ * @return void
+ */
+ onRefreshPostScreen: function( data ) {
+
+ // Extract vars.
+ var select = wp.data.select( 'core/edit-post' );
+ var dispatch = wp.data.dispatch( 'core/edit-post' );
+
+ // Load current metabox locations and data.
+ var locations = {};
+ select.getActiveMetaBoxLocations().map(function( location ){
+ locations[ location ] = select.getMetaBoxesPerLocation( location );
+ });
+
+ // Generate flat array of existing ids.
+ var ids = [];
+ for( var k in locations ) {
+ locations[k].map(function( m ){
+ ids.push( m.id );
+ });
+ }
+
+ // Append new ACF metaboxes (ignore those which already exist).
+ data.results.filter(function( r ){
+ return ( ids.indexOf( r.id ) === -1 );
+ }).map(function( result, i ){
+
+ // Ensure location exists.
+ var location = result.position;
+ locations[ location ] = locations[ location ] || [];
+
+ // Append.
+ locations[ location ].push({
+ id: result.id,
+ title: result.title
+ });
+ });
+
+ // Remove hidden ACF metaboxes.
+ for( var k in locations ) {
+ locations[k] = locations[k].filter(function( m ){
+ return ( data.hidden.indexOf( m.id ) === -1 );
+ });
+ }
+
+ // Update state.
+ dispatch.setAvailableMetaBoxesPerLocation( locations );
+ }
+ });
-(function ($, undefined) {
- acf.screen = new acf.Model({
- active: true,
- xhr: false,
- timeout: false,
- wait: 'load',
- events: {
- 'change #page_template': 'onChange',
- 'change #parent_id': 'onChange',
- 'change #post-formats-select': 'onChange',
- 'change .categorychecklist': 'onChange',
- 'change .tagsdiv': 'onChange',
- 'change .acf-taxonomy-field[data-save="1"]': 'onChange',
- 'change #product-type': 'onChange'
- },
- isPost: function () {
- return acf.get('screen') === 'post';
- },
- isUser: function () {
- return acf.get('screen') === 'user';
- },
- isTaxonomy: function () {
- return acf.get('screen') === 'taxonomy';
- },
- isAttachment: function () {
- return acf.get('screen') === 'attachment';
- },
- isNavMenu: function () {
- return acf.get('screen') === 'nav_menu';
- },
- isWidget: function () {
- return acf.get('screen') === 'widget';
- },
- isComment: function () {
- return acf.get('screen') === 'comment';
- },
- getPageTemplate: function () {
- var $el = $('#page_template');
- return $el.length ? $el.val() : null;
- },
- getPageParent: function (e, $el) {
- var $el = $('#parent_id');
- return $el.length ? $el.val() : null;
- },
- getPageType: function (e, $el) {
- return this.getPageParent() ? 'child' : 'parent';
- },
- getPostType: function () {
- return $('#post_type').val();
- },
- getPostFormat: function (e, $el) {
- var $el = $('#post-formats-select input:checked');
-
- if ($el.length) {
- var val = $el.val();
- return val == '0' ? 'standard' : val;
- }
-
- return null;
- },
- getPostCoreTerms: function () {
- // vars
- var terms = {}; // serialize WP taxonomy postboxes
-
- var data = acf.serialize($('.categorydiv, .tagsdiv')); // use tax_input (tag, custom-taxonomy) when possible.
- // this data is already formatted in taxonomy => [terms].
-
- if (data.tax_input) {
- terms = data.tax_input;
- } // append "category" which uses a different name
-
-
- if (data.post_category) {
- terms.category = data.post_category;
- } // convert any string values (tags) into array format
-
-
- for (var tax in terms) {
- if (!acf.isArray(terms[tax])) {
- terms[tax] = terms[tax].split(/,[\s]?/);
- }
- } // return
-
-
- return terms;
- },
- getPostTerms: function () {
- // Get core terms.
- var terms = this.getPostCoreTerms(); // loop over taxonomy fields and add their values
-
- acf.getFields({
- type: 'taxonomy'
- }).map(function (field) {
- // ignore fields that don't save
- if (!field.get('save')) {
- return;
- } // vars
-
-
- var val = field.val();
- var tax = field.get('taxonomy'); // check val
-
- if (val) {
- // ensure terms exists
- terms[tax] = terms[tax] || []; // ensure val is an array
-
- val = acf.isArray(val) ? val : [val]; // append
-
- terms[tax] = terms[tax].concat(val);
- }
- }); // add WC product type
-
- if ((productType = this.getProductType()) !== null) {
- terms.product_type = [productType];
- } // remove duplicate values
-
-
- for (var tax in terms) {
- terms[tax] = acf.uniqueArray(terms[tax]);
- } // return
-
-
- return terms;
- },
- getProductType: function () {
- var $el = $('#product-type');
- return $el.length ? $el.val() : null;
- },
- check: function () {
- // bail early if not for post
- if (acf.get('screen') !== 'post') {
- return;
- } // abort XHR if is already loading AJAX data
-
-
- if (this.xhr) {
- this.xhr.abort();
- } // vars
-
-
- var ajaxData = acf.parseArgs(this.data, {
- action: 'acf/ajax/check_screen',
- screen: acf.get('screen'),
- exists: []
- }); // post id
-
- if (this.isPost()) {
- ajaxData.post_id = acf.get('post_id');
- } // post type
-
-
- if ((postType = this.getPostType()) !== null) {
- ajaxData.post_type = postType;
- } // page template
-
-
- if ((pageTemplate = this.getPageTemplate()) !== null) {
- ajaxData.page_template = pageTemplate;
- } // page parent
-
-
- if ((pageParent = this.getPageParent()) !== null) {
- ajaxData.page_parent = pageParent;
- } // page type
-
-
- if ((pageType = this.getPageType()) !== null) {
- ajaxData.page_type = pageType;
- } // post format
-
-
- if ((postFormat = this.getPostFormat()) !== null) {
- ajaxData.post_format = postFormat;
- } // post terms
-
-
- if ((postTerms = this.getPostTerms()) !== null) {
- ajaxData.post_terms = postTerms;
- } // add array of existing postboxes to increase performance and reduce JSON HTML
-
-
- acf.getPostboxes().map(function (postbox) {
- ajaxData.exists.push(postbox.get('key'));
- }); // filter
-
- ajaxData = acf.applyFilters('check_screen_args', ajaxData); // success
-
- var onSuccess = function (json) {
- // Render post screen.
- if (acf.get('screen') == 'post') {
- this.renderPostScreen(json); // Render user screen.
- } else if (acf.get('screen') == 'user') {
- this.renderUserScreen(json);
- } // action
-
-
- acf.doAction('check_screen_complete', json, ajaxData);
- }; // ajax
-
-
- this.xhr = $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(ajaxData),
- type: 'post',
- dataType: 'json',
- context: this,
- success: onSuccess
- });
- },
- onChange: function (e, $el) {
- this.setTimeout(this.check, 1);
- },
- renderPostScreen: function (data) {
- // Helper function to copy events
- var copyEvents = function ($from, $to) {
- var events = $._data($from[0]).events;
-
- for (var type in events) {
- for (var i = 0; i < events[type].length; i++) {
- $to.on(type, events[type][i].handler);
- }
- }
- }; // Helper function to sort metabox.
-
-
- var sortMetabox = function (id, ids) {
- // Find position of id within ids.
- var index = ids.indexOf(id); // Bail early if index not found.
-
- if (index == -1) {
- return false;
- } // Loop over metaboxes behind (in reverse order).
-
-
- for (var i = index - 1; i >= 0; i--) {
- if ($('#' + ids[i]).length) {
- return $('#' + ids[i]).after($('#' + id));
- }
- } // Loop over metaboxes infront.
-
-
- for (var i = index + 1; i < ids.length; i++) {
- if ($('#' + ids[i]).length) {
- return $('#' + ids[i]).before($('#' + id));
- }
- } // Return false if not sorted.
-
-
- return false;
- }; // Keep track of visible and hidden postboxes.
-
-
- data.visible = [];
- data.hidden = []; // Show these postboxes.
-
- data.results = data.results.map(function (result, i) {
- // vars
- var postbox = acf.getPostbox(result.id); // Prevent "acf_after_title" position in Block Editor.
-
- if (acf.isGutenberg() && result.position == "acf_after_title") {
- result.position = 'normal';
- } // Create postbox if doesn't exist.
-
-
- if (!postbox) {
- var wpMinorVersion = parseFloat(acf.get('wp_version'));
-
- if (wpMinorVersion >= 5.5) {
- var postboxHeader = [''].join('');
- } else {
- var postboxHeader = ['', 'Toggle panel: ' + acf.escHtml(result.title) + ' ', ' ', ' ', '', '' + acf.escHtml(result.title) + ' ', ' '].join('');
- } // Create it.
-
-
- var $postbox = $(['', postboxHeader, '
', result.html, '
', '
'].join('')); // Create new hide toggle.
-
- if ($('#adv-settings').length) {
- var $prefs = $('#adv-settings .metabox-prefs');
- var $label = $(['', ' ', ' ' + result.title, ' '].join('')); // Copy default WP events onto checkbox.
-
- copyEvents($prefs.find('input').first(), $label.find('input')); // Append hide label
-
- $prefs.append($label);
- } // Copy default WP events onto metabox.
-
-
- if ($('.postbox').length) {
- copyEvents($('.postbox .handlediv').first(), $postbox.children('.handlediv'));
- copyEvents($('.postbox .hndle').first(), $postbox.children('.hndle'));
- } // Append metabox to the bottom of "side-sortables".
-
-
- if (result.position === 'side') {
- $('#' + result.position + '-sortables').append($postbox); // Prepend metabox to the top of "normal-sortbables".
- } else {
- $('#' + result.position + '-sortables').prepend($postbox);
- } // Position metabox amongst existing ACF metaboxes within the same location.
-
-
- var order = [];
- data.results.map(function (_result) {
- if (result.position === _result.position && $('#' + result.position + '-sortables #' + _result.id).length) {
- order.push(_result.id);
- }
- });
- sortMetabox(result.id, order); // Check 'sorted' for user preference.
-
- if (data.sorted) {
- // Loop over each position (acf_after_title, side, normal).
- for (var position in data.sorted) {
- // Explode string into array of ids.
- var order = data.sorted[position].split(','); // Position metabox relative to order.
-
- if (sortMetabox(result.id, order)) {
- break;
- }
- }
- } // Initalize it (modifies HTML).
-
-
- postbox = acf.newPostbox(result); // Trigger action.
-
- acf.doAction('append', $postbox);
- acf.doAction('append_postbox', postbox);
- } // show postbox
-
-
- postbox.showEnable(); // append
-
- data.visible.push(result.id); // Return result (may have changed).
-
- return result;
- }); // Hide these postboxes.
-
- acf.getPostboxes().map(function (postbox) {
- if (data.visible.indexOf(postbox.get('id')) === -1) {
- // Hide postbox.
- postbox.hideDisable(); // Append to data.
-
- data.hidden.push(postbox.get('id'));
- }
- }); // Update style.
-
- $('#acf-style').html(data.style); // Do action.
-
- acf.doAction('refresh_post_screen', data);
- },
- renderUserScreen: function (json) {}
- });
- /**
- * gutenScreen
- *
- * Adds compatibility with the Gutenberg edit screen.
- *
- * @date 11/12/18
- * @since 5.8.0
- *
- * @param void
- * @return void
- */
-
- var gutenScreen = new acf.Model({
- // Keep a reference to the most recent post attributes.
- postEdits: {},
- // Wait until assets have been loaded.
- wait: 'prepare',
- initialize: function () {
- // Bail early if not Gutenberg.
- if (!acf.isGutenberg()) {
- return;
- } // Listen for changes (use debounced version as this can fires often).
-
-
- wp.data.subscribe(acf.debounce(this.onChange).bind(this)); // Customize "acf.screen.get" functions.
-
- acf.screen.getPageTemplate = this.getPageTemplate;
- acf.screen.getPageParent = this.getPageParent;
- acf.screen.getPostType = this.getPostType;
- acf.screen.getPostFormat = this.getPostFormat;
- acf.screen.getPostCoreTerms = this.getPostCoreTerms; // Disable unload
-
- acf.unload.disable(); // Refresh metaboxes since WP 5.3.
-
- var wpMinorVersion = parseFloat(acf.get('wp_version'));
-
- if (wpMinorVersion >= 5.3) {
- this.addAction('refresh_post_screen', this.onRefreshPostScreen);
- } // Trigger "refresh" after WP has moved metaboxes into place.
-
-
- wp.domReady(acf.refresh);
- },
- onChange: function () {
- // Determine attributes that can trigger a refresh.
- var attributes = ['template', 'parent', 'format']; // Append taxonomy attribute names to this list.
-
- (wp.data.select('core').getTaxonomies() || []).map(function (taxonomy) {
- attributes.push(taxonomy.rest_base);
- }); // Get relevant current post edits.
-
- var _postEdits = wp.data.select('core/editor').getPostEdits();
-
- var postEdits = {};
- attributes.map(function (k) {
- if (_postEdits[k] !== undefined) {
- postEdits[k] = _postEdits[k];
- }
- }); // Detect change.
-
- if (JSON.stringify(postEdits) !== JSON.stringify(this.postEdits)) {
- this.postEdits = postEdits; // Check screen.
-
- acf.screen.check();
- }
- },
- getPageTemplate: function () {
- return wp.data.select('core/editor').getEditedPostAttribute('template');
- },
- getPageParent: function (e, $el) {
- return wp.data.select('core/editor').getEditedPostAttribute('parent');
- },
- getPostType: function () {
- return wp.data.select('core/editor').getEditedPostAttribute('type');
- },
- getPostFormat: function (e, $el) {
- return wp.data.select('core/editor').getEditedPostAttribute('format');
- },
- getPostCoreTerms: function () {
- // vars
- var terms = {}; // Loop over taxonomies.
-
- var taxonomies = wp.data.select('core').getTaxonomies() || [];
- taxonomies.map(function (taxonomy) {
- // Append selected taxonomies to terms object.
- var postTerms = wp.data.select('core/editor').getEditedPostAttribute(taxonomy.rest_base);
-
- if (postTerms) {
- terms[taxonomy.slug] = postTerms;
- }
- }); // return
-
- return terms;
- },
-
- /**
- * onRefreshPostScreen
- *
- * Fires after the Post edit screen metaboxs are refreshed to update the Block Editor API state.
- *
- * @date 11/11/19
- * @since 5.8.7
- *
- * @param object data The "check_screen" JSON response data.
- * @return void
- */
- onRefreshPostScreen: function (data) {
- // Extract vars.
- var select = wp.data.select('core/edit-post');
- var dispatch = wp.data.dispatch('core/edit-post'); // Load current metabox locations and data.
-
- var locations = {};
- select.getActiveMetaBoxLocations().map(function (location) {
- locations[location] = select.getMetaBoxesPerLocation(location);
- }); // Generate flat array of existing ids.
-
- var ids = [];
-
- for (var k in locations) {
- locations[k].map(function (m) {
- ids.push(m.id);
- });
- } // Append new ACF metaboxes (ignore those which already exist).
-
-
- data.results.filter(function (r) {
- return ids.indexOf(r.id) === -1;
- }).map(function (result, i) {
- // Ensure location exists.
- var location = result.position;
- locations[location] = locations[location] || []; // Append.
-
- locations[location].push({
- id: result.id,
- title: result.title
- });
- }); // Remove hidden ACF metaboxes.
-
- for (var k in locations) {
- locations[k] = locations[k].filter(function (m) {
- return data.hidden.indexOf(m.id) === -1;
- });
- } // Update state.
-
-
- dispatch.setAvailableMetaBoxesPerLocation(locations);
- }
- });
})(jQuery);
-
-(function ($, undefined) {
- /**
- * acf.newSelect2
- *
- * description
- *
- * @date 13/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- acf.newSelect2 = function ($select, props) {
- // defaults
- props = acf.parseArgs(props, {
- allowNull: false,
- placeholder: '',
- multiple: false,
- field: false,
- ajax: false,
- ajaxAction: '',
- ajaxData: function (data) {
- return data;
- },
- ajaxResults: function (json) {
- return json;
- }
- }); // initialize
-
- if (getVersion() == 4) {
- var select2 = new Select2_4($select, props);
- } else {
- var select2 = new Select2_3($select, props);
- } // actions
-
-
- acf.doAction('new_select2', select2); // return
-
- return select2;
- };
- /**
- * getVersion
- *
- * description
- *
- * @date 13/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- function getVersion() {
- // v4
- if (acf.isset(window, 'jQuery', 'fn', 'select2', 'amd')) {
- return 4;
- } // v3
-
-
- if (acf.isset(window, 'Select2')) {
- return 3;
- } // return
-
-
- return false;
- }
- /**
- * Select2
- *
- * description
- *
- * @date 13/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- var Select2 = acf.Model.extend({
- setup: function ($select, props) {
- $.extend(this.data, props);
- this.$el = $select;
- },
- initialize: function () {},
- selectOption: function (value) {
- var $option = this.getOption(value);
-
- if (!$option.prop('selected')) {
- $option.prop('selected', true).trigger('change');
- }
- },
- unselectOption: function (value) {
- var $option = this.getOption(value);
-
- if ($option.prop('selected')) {
- $option.prop('selected', false).trigger('change');
- }
- },
- getOption: function (value) {
- return this.$('option[value="' + value + '"]');
- },
- addOption: function (option) {
- // defaults
- option = acf.parseArgs(option, {
- id: '',
- text: '',
- selected: false
- }); // vars
-
- var $option = this.getOption(option.id); // append
-
- if (!$option.length) {
- $option = $(' ');
- $option.html(option.text);
- $option.attr('value', option.id);
- $option.prop('selected', option.selected);
- this.$el.append($option);
- } // chain
-
-
- return $option;
- },
- getValue: function () {
- // vars
- var val = [];
- var $options = this.$el.find('option:selected'); // bail early if no selected
-
- if (!$options.exists()) {
- return val;
- } // sort by attribute
-
-
- $options = $options.sort(function (a, b) {
- return +a.getAttribute('data-i') - +b.getAttribute('data-i');
- }); // loop
-
- $options.each(function () {
- var $el = $(this);
- val.push({
- $el: $el,
- id: $el.attr('value'),
- text: $el.text()
- });
- }); // return
-
- return val;
- },
- mergeOptions: function () {},
- getChoices: function () {
- // callback
- var crawl = function ($parent) {
- // vars
- var choices = []; // loop
-
- $parent.children().each(function () {
- // vars
- var $child = $(this); // optgroup
-
- if ($child.is('optgroup')) {
- choices.push({
- text: $child.attr('label'),
- children: crawl($child)
- }); // option
- } else {
- choices.push({
- id: $child.attr('value'),
- text: $child.text()
- });
- }
- }); // return
-
- return choices;
- }; // crawl
-
-
- return crawl(this.$el);
- },
- getAjaxData: function (params) {
- // vars
- var ajaxData = {
- action: this.get('ajaxAction'),
- s: params.term || '',
- paged: params.page || 1
- }; // field helper
-
- var field = this.get('field');
-
- if (field) {
- ajaxData.field_key = field.get('key');
- } // callback
-
-
- var callback = this.get('ajaxData');
-
- if (callback) {
- ajaxData = callback.apply(this, [ajaxData, params]);
- } // filter
-
-
- ajaxData = acf.applyFilters('select2_ajax_data', ajaxData, this.data, this.$el, field || false, this); // return
-
- return acf.prepareForAjax(ajaxData);
- },
- getAjaxResults: function (json, params) {
- // defaults
- json = acf.parseArgs(json, {
- results: false,
- more: false
- }); // callback
-
- var callback = this.get('ajaxResults');
-
- if (callback) {
- json = callback.apply(this, [json, params]);
- } // filter
-
-
- json = acf.applyFilters('select2_ajax_results', json, params, this); // return
-
- return json;
- },
- processAjaxResults: function (json, params) {
- // vars
- var json = this.getAjaxResults(json, params); // change more to pagination
-
- if (json.more) {
- json.pagination = {
- more: true
- };
- } // merge together groups
-
-
- setTimeout($.proxy(this.mergeOptions, this), 1); // return
-
- return json;
- },
- destroy: function () {
- // destroy via api
- if (this.$el.data('select2')) {
- this.$el.select2('destroy');
- } // destory via HTML (duplicating HTML does not contain data)
-
-
- this.$el.siblings('.select2-container').remove();
- }
- });
- /**
- * Select2_4
- *
- * description
- *
- * @date 13/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var Select2_4 = Select2.extend({
- initialize: function () {
- // vars
- var $select = this.$el;
- var options = {
- width: '100%',
- allowClear: this.get('allowNull'),
- placeholder: this.get('placeholder'),
- multiple: this.get('multiple'),
- data: [],
- escapeMarkup: function (string) {
- return acf.escHtml(string);
- }
- }; // multiple
-
- if (options.multiple) {
- // reorder options
- this.getValue().map(function (item) {
- item.$el.detach().appendTo($select);
- });
- } // Temporarily remove conflicting attribute.
-
-
- var attrAjax = $select.attr('data-ajax');
-
- if (attrAjax !== undefined) {
- $select.removeData('ajax');
- $select.removeAttr('data-ajax');
- } // ajax
-
-
- if (this.get('ajax')) {
- options.ajax = {
- url: acf.get('ajaxurl'),
- delay: 250,
- dataType: 'json',
- type: 'post',
- cache: false,
- data: $.proxy(this.getAjaxData, this),
- processResults: $.proxy(this.processAjaxResults, this)
- };
- } // filter for 3rd party customization
- //options = acf.applyFilters( 'select2_args', options, $select, this );
-
-
- var field = this.get('field');
- options = acf.applyFilters('select2_args', options, $select, this.data, field || false, this); // add select2
-
- $select.select2(options); // get container (Select2 v4 does not return this from constructor)
-
- var $container = $select.next('.select2-container'); // multiple
-
- if (options.multiple) {
- // vars
- var $ul = $container.find('ul'); // sortable
-
- $ul.sortable({
- stop: function (e) {
- // loop
- $ul.find('.select2-selection__choice').each(function () {
- // vars
- var $option = $($(this).data('data').element); // detach and re-append to end
-
- $option.detach().appendTo($select);
- }); // trigger change on input (JS error if trigger on select)
-
- $select.trigger('change');
- }
- }); // on select, move to end
-
- $select.on('select2:select', this.proxy(function (e) {
- this.getOption(e.params.data.id).detach().appendTo(this.$el);
- }));
- } // add class
-
-
- $container.addClass('-acf'); // Add back temporarily removed attr.
-
- if (attrAjax !== undefined) {
- $select.attr('data-ajax', attrAjax);
- } // action for 3rd party customization
-
-
- acf.doAction('select2_init', $select, options, this.data, field || false, this);
- },
- mergeOptions: function () {
- // vars
- var $prevOptions = false;
- var $prevGroup = false; // loop
-
- $('.select2-results__option[role="group"]').each(function () {
- // vars
- var $options = $(this).children('ul');
- var $group = $(this).children('strong'); // compare to previous
-
- if ($prevGroup && $prevGroup.text() === $group.text()) {
- $prevOptions.append($options.children());
- $(this).remove();
- return;
- } // update vars
-
-
- $prevOptions = $options;
- $prevGroup = $group;
- });
- }
- });
- /**
- * Select2_3
- *
- * description
- *
- * @date 13/1/18
- * @since 5.6.5
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var Select2_3 = Select2.extend({
- initialize: function () {
- // vars
- var $select = this.$el;
- var value = this.getValue();
- var multiple = this.get('multiple');
- var options = {
- width: '100%',
- allowClear: this.get('allowNull'),
- placeholder: this.get('placeholder'),
- separator: '||',
- multiple: this.get('multiple'),
- data: this.getChoices(),
- escapeMarkup: function (string) {
- return acf.escHtml(string);
- },
- dropdownCss: {
- 'z-index': '999999999'
- },
- initSelection: function (element, callback) {
- if (multiple) {
- callback(value);
- } else {
- callback(value.shift());
- }
- }
- }; // get hidden input
-
- var $input = $select.siblings('input');
-
- if (!$input.length) {
- $input = $(' ');
- $select.before($input);
- } // set input value
-
-
- inputValue = value.map(function (item) {
- return item.id;
- }).join('||');
- $input.val(inputValue); // multiple
-
- if (options.multiple) {
- // reorder options
- value.map(function (item) {
- item.$el.detach().appendTo($select);
- });
- } // remove blank option as we have a clear all button
-
-
- if (options.allowClear) {
- options.data = options.data.filter(function (item) {
- return item.id !== '';
- });
- } // remove conflicting atts
-
-
- $select.removeData('ajax');
- $select.removeAttr('data-ajax'); // ajax
-
- if (this.get('ajax')) {
- options.ajax = {
- url: acf.get('ajaxurl'),
- quietMillis: 250,
- dataType: 'json',
- type: 'post',
- cache: false,
- data: $.proxy(this.getAjaxData, this),
- results: $.proxy(this.processAjaxResults, this)
- };
- } // filter for 3rd party customization
-
-
- var field = this.get('field');
- options = acf.applyFilters('select2_args', options, $select, this.data, field || false, this); // add select2
-
- $input.select2(options); // get container
-
- var $container = $input.select2('container'); // helper to find this select's option
-
- var getOption = $.proxy(this.getOption, this); // multiple
-
- if (options.multiple) {
- // vars
- var $ul = $container.find('ul'); // sortable
-
- $ul.sortable({
- stop: function () {
- // loop
- $ul.find('.select2-search-choice').each(function () {
- // vars
- var data = $(this).data('select2Data');
- var $option = getOption(data.id); // detach and re-append to end
-
- $option.detach().appendTo($select);
- }); // trigger change on input (JS error if trigger on select)
-
- $select.trigger('change');
- }
- });
- } // on select, create option and move to end
-
-
- $input.on('select2-selecting', function (e) {
- // vars
- var item = e.choice;
- var $option = getOption(item.id); // create if doesn't exist
-
- if (!$option.length) {
- $option = $('' + item.text + ' ');
- } // detach and re-append to end
-
-
- $option.detach().appendTo($select);
- }); // add class
-
- $container.addClass('-acf'); // action for 3rd party customization
-
- acf.doAction('select2_init', $select, options, this.data, field || false, this); // change
-
- $input.on('change', function () {
- var val = $input.val();
-
- if (val.indexOf('||')) {
- val = val.split('||');
- }
-
- $select.val(val).trigger('change');
- }); // hide select
-
- $select.hide();
- },
- mergeOptions: function () {
- // vars
- var $prevOptions = false;
- var $prevGroup = false; // loop
-
- $('#select2-drop .select2-result-with-children').each(function () {
- // vars
- var $options = $(this).children('ul');
- var $group = $(this).children('.select2-result-label'); // compare to previous
-
- if ($prevGroup && $prevGroup.text() === $group.text()) {
- $prevGroup.append($options.children());
- $(this).remove();
- return;
- } // update vars
-
-
- $prevOptions = $options;
- $prevGroup = $group;
- });
- },
- getAjaxData: function (term, page) {
- // create Select2 v4 params
- var params = {
- term: term,
- page: page
- }; // return
-
- return Select2.prototype.getAjaxData.apply(this, [params]);
- }
- }); // manager
-
- var select2Manager = new acf.Model({
- priority: 5,
- wait: 'prepare',
- actions: {
- 'duplicate': 'onDuplicate'
- },
- initialize: function () {
- // vars
- var locale = acf.get('locale');
- var rtl = acf.get('rtl');
- var l10n = acf.get('select2L10n');
- var version = getVersion(); // bail ealry if no l10n
-
- if (!l10n) {
- return false;
- } // bail early if 'en'
-
-
- if (locale.indexOf('en') === 0) {
- return false;
- } // initialize
-
-
- if (version == 4) {
- this.addTranslations4();
- } else if (version == 3) {
- this.addTranslations3();
- }
- },
- addTranslations4: function () {
- // vars
- var l10n = acf.get('select2L10n');
- var locale = acf.get('locale'); // modify local to match html[lang] attribute (used by Select2)
-
- locale = locale.replace('_', '-'); // select2L10n
-
- var select2L10n = {
- errorLoading: function () {
- return l10n.load_fail;
- },
- inputTooLong: function (args) {
- var overChars = args.input.length - args.maximum;
-
- if (overChars > 1) {
- return l10n.input_too_long_n.replace('%d', overChars);
- }
-
- return l10n.input_too_long_1;
- },
- inputTooShort: function (args) {
- var remainingChars = args.minimum - args.input.length;
-
- if (remainingChars > 1) {
- return l10n.input_too_short_n.replace('%d', remainingChars);
- }
-
- return l10n.input_too_short_1;
- },
- loadingMore: function () {
- return l10n.load_more;
- },
- maximumSelected: function (args) {
- var maximum = args.maximum;
-
- if (maximum > 1) {
- return l10n.selection_too_long_n.replace('%d', maximum);
- }
-
- return l10n.selection_too_long_1;
- },
- noResults: function () {
- return l10n.matches_0;
- },
- searching: function () {
- return l10n.searching;
- }
- }; // append
-
- jQuery.fn.select2.amd.define('select2/i18n/' + locale, [], function () {
- return select2L10n;
- });
- },
- addTranslations3: function () {
- // vars
- var l10n = acf.get('select2L10n');
- var locale = acf.get('locale'); // modify local to match html[lang] attribute (used by Select2)
-
- locale = locale.replace('_', '-'); // select2L10n
-
- var select2L10n = {
- formatMatches: function (matches) {
- if (matches > 1) {
- return l10n.matches_n.replace('%d', matches);
- }
-
- return l10n.matches_1;
- },
- formatNoMatches: function () {
- return l10n.matches_0;
- },
- formatAjaxError: function () {
- return l10n.load_fail;
- },
- formatInputTooShort: function (input, min) {
- var remainingChars = min - input.length;
-
- if (remainingChars > 1) {
- return l10n.input_too_short_n.replace('%d', remainingChars);
- }
-
- return l10n.input_too_short_1;
- },
- formatInputTooLong: function (input, max) {
- var overChars = input.length - max;
-
- if (overChars > 1) {
- return l10n.input_too_long_n.replace('%d', overChars);
- }
-
- return l10n.input_too_long_1;
- },
- formatSelectionTooBig: function (maximum) {
- if (maximum > 1) {
- return l10n.selection_too_long_n.replace('%d', maximum);
- }
-
- return l10n.selection_too_long_1;
- },
- formatLoadMore: function () {
- return l10n.load_more;
- },
- formatSearching: function () {
- return l10n.searching;
- }
- }; // ensure locales exists
-
- $.fn.select2.locales = $.fn.select2.locales || {}; // append
-
- $.fn.select2.locales[locale] = select2L10n;
- $.extend($.fn.select2.defaults, select2L10n);
- },
- onDuplicate: function ($el, $el2) {
- $el2.find('.select2-container').remove();
- }
- });
+(function($, undefined){
+
+ /**
+ * acf.newSelect2
+ *
+ * description
+ *
+ * @date 13/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.newSelect2 = function( $select, props ){
+
+ // defaults
+ props = acf.parseArgs(props, {
+ allowNull: false,
+ placeholder: '',
+ multiple: false,
+ field: false,
+ ajax: false,
+ ajaxAction: '',
+ ajaxData: function( data ){ return data; },
+ ajaxResults: function( json ){ return json; },
+ });
+
+ // initialize
+ if( getVersion() == 4 ) {
+ var select2 = new Select2_4( $select, props );
+ } else {
+ var select2 = new Select2_3( $select, props );
+ }
+
+ // actions
+ acf.doAction('new_select2', select2);
+
+ // return
+ return select2;
+ };
+
+ /**
+ * getVersion
+ *
+ * description
+ *
+ * @date 13/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ function getVersion() {
+
+ // v4
+ if( acf.isset(window, 'jQuery', 'fn', 'select2', 'amd') ) {
+ return 4;
+ }
+
+ // v3
+ if( acf.isset(window, 'Select2') ) {
+ return 3;
+ }
+
+ // return
+ return false;
+ }
+
+ /**
+ * Select2
+ *
+ * description
+ *
+ * @date 13/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var Select2 = acf.Model.extend({
+
+ setup: function( $select, props ){
+ $.extend(this.data, props);
+ this.$el = $select;
+ },
+
+ initialize: function(){
+
+ },
+
+ selectOption: function( value ){
+ var $option = this.getOption( value );
+ if( !$option.prop('selected') ) {
+ $option.prop('selected', true).trigger('change');
+ }
+ },
+
+ unselectOption: function( value ){
+ var $option = this.getOption( value );
+ if( $option.prop('selected') ) {
+ $option.prop('selected', false).trigger('change');
+ }
+ },
+
+ getOption: function( value ){
+ return this.$('option[value="' + value + '"]');
+ },
+
+ addOption: function( option ){
+
+ // defaults
+ option = acf.parseArgs(option, {
+ id: '',
+ text: '',
+ selected: false
+ });
+
+ // vars
+ var $option = this.getOption( option.id );
+
+ // append
+ if( !$option.length ) {
+ $option = $(' ');
+ $option.html( option.text );
+ $option.attr('value', option.id);
+ $option.prop('selected', option.selected);
+ this.$el.append($option);
+ }
+
+ // chain
+ return $option;
+ },
+
+ getValue: function(){
+
+ // vars
+ var val = [];
+ var $options = this.$el.find('option:selected');
+
+ // bail early if no selected
+ if( !$options.exists() ) {
+ return val;
+ }
+
+ // sort by attribute
+ $options = $options.sort(function(a, b) {
+ return +a.getAttribute('data-i') - +b.getAttribute('data-i');
+ });
+
+ // loop
+ $options.each(function(){
+ var $el = $(this);
+ val.push({
+ $el: $el,
+ id: $el.attr('value'),
+ text: $el.text(),
+ });
+ });
+
+ // return
+ return val;
+
+ },
+
+ mergeOptions: function(){
+
+ },
+
+ getChoices: function(){
+
+ // callback
+ var crawl = function( $parent ){
+
+ // vars
+ var choices = [];
+
+ // loop
+ $parent.children().each(function(){
+
+ // vars
+ var $child = $(this);
+
+ // optgroup
+ if( $child.is('optgroup') ) {
+
+ choices.push({
+ text: $child.attr('label'),
+ children: crawl( $child )
+ });
+
+ // option
+ } else {
+
+ choices.push({
+ id: $child.attr('value'),
+ text: $child.text()
+ });
+ }
+ });
+
+ // return
+ return choices;
+ };
+
+ // crawl
+ return crawl( this.$el );
+ },
+
+ getAjaxData: function( params ){
+
+ // vars
+ var ajaxData = {
+ action: this.get('ajaxAction'),
+ s: params.term || '',
+ paged: params.page || 1
+ };
+
+ // field helper
+ var field = this.get('field');
+ if( field ) {
+ ajaxData.field_key = field.get('key');
+ }
+
+ // callback
+ var callback = this.get('ajaxData');
+ if( callback ) {
+ ajaxData = callback.apply( this, [ajaxData, params] );
+ }
+
+ // filter
+ ajaxData = acf.applyFilters( 'select2_ajax_data', ajaxData, this.data, this.$el, (field || false), this );
+
+ // return
+ return acf.prepareForAjax(ajaxData);
+ },
+
+ getAjaxResults: function( json, params ){
+
+ // defaults
+ json = acf.parseArgs(json, {
+ results: false,
+ more: false,
+ });
+
+ // callback
+ var callback = this.get('ajaxResults');
+ if( callback ) {
+ json = callback.apply( this, [json, params] );
+ }
+
+ // filter
+ json = acf.applyFilters( 'select2_ajax_results', json, params, this );
+
+ // return
+ return json;
+ },
+
+ processAjaxResults: function( json, params ){
+
+ // vars
+ var json = this.getAjaxResults( json, params );
+
+ // change more to pagination
+ if( json.more ) {
+ json.pagination = { more: true };
+ }
+
+ // merge together groups
+ setTimeout($.proxy(this.mergeOptions, this), 1);
+
+ // return
+ return json;
+ },
+
+ destroy: function(){
+
+ // destroy via api
+ if( this.$el.data('select2') ) {
+ this.$el.select2('destroy');
+ }
+
+ // destory via HTML (duplicating HTML does not contain data)
+ this.$el.siblings('.select2-container').remove();
+ }
+
+ });
+
+
+ /**
+ * Select2_4
+ *
+ * description
+ *
+ * @date 13/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var Select2_4 = Select2.extend({
+
+ initialize: function(){
+
+ // vars
+ var $select = this.$el;
+ var options = {
+ width: '100%',
+ allowClear: this.get('allowNull'),
+ placeholder: this.get('placeholder'),
+ multiple: this.get('multiple'),
+ data: [],
+ escapeMarkup: function( string ){
+ return acf.escHtml( string );
+ },
+ };
+
+ // multiple
+ if( options.multiple ) {
+
+ // reorder options
+ this.getValue().map(function( item ){
+ item.$el.detach().appendTo( $select );
+ });
+ }
+
+ // Temporarily remove conflicting attribute.
+ var attrAjax = $select.attr( 'data-ajax' );
+ if( attrAjax !== undefined ) {
+ $select.removeData('ajax');
+ $select.removeAttr('data-ajax');
+ }
+
+ // ajax
+ if( this.get('ajax') ) {
+
+ options.ajax = {
+ url: acf.get('ajaxurl'),
+ delay: 250,
+ dataType: 'json',
+ type: 'post',
+ cache: false,
+ data: $.proxy(this.getAjaxData, this),
+ processResults: $.proxy(this.processAjaxResults, this),
+ };
+ }
+
+ // filter for 3rd party customization
+ //options = acf.applyFilters( 'select2_args', options, $select, this );
+ var field = this.get('field');
+ options = acf.applyFilters( 'select2_args', options, $select, this.data, (field || false), this );
+
+ // add select2
+ $select.select2( options );
+
+ // get container (Select2 v4 does not return this from constructor)
+ var $container = $select.next('.select2-container');
+
+ // multiple
+ if( options.multiple ) {
+
+ // vars
+ var $ul = $container.find('ul');
+
+ // sortable
+ $ul.sortable({
+ stop: function( e ) {
+
+ // loop
+ $ul.find('.select2-selection__choice').each(function() {
+
+ // vars
+ var $option = $( $(this).data('data').element );
+
+ // detach and re-append to end
+ $option.detach().appendTo( $select );
+ });
+
+ // trigger change on input (JS error if trigger on select)
+ $select.trigger('change');
+ }
+ });
+
+ // on select, move to end
+ $select.on('select2:select', this.proxy(function( e ){
+ this.getOption( e.params.data.id ).detach().appendTo( this.$el );
+ }));
+ }
+
+ // add class
+ $container.addClass('-acf');
+
+ // Add back temporarily removed attr.
+ if( attrAjax !== undefined ) {
+ $select.attr('data-ajax', attrAjax);
+ }
+
+ // action for 3rd party customization
+ acf.doAction('select2_init', $select, options, this.data, (field || false), this);
+ },
+
+ mergeOptions: function(){
+
+ // vars
+ var $prevOptions = false;
+ var $prevGroup = false;
+
+ // loop
+ $('.select2-results__option[role="group"]').each(function(){
+
+ // vars
+ var $options = $(this).children('ul');
+ var $group = $(this).children('strong');
+
+ // compare to previous
+ if( $prevGroup && $prevGroup.text() === $group.text() ) {
+ $prevOptions.append( $options.children() );
+ $(this).remove();
+ return;
+ }
+
+ // update vars
+ $prevOptions = $options;
+ $prevGroup = $group;
+
+ });
+ },
+
+ });
+
+ /**
+ * Select2_3
+ *
+ * description
+ *
+ * @date 13/1/18
+ * @since 5.6.5
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var Select2_3 = Select2.extend({
+
+ initialize: function(){
+
+ // vars
+ var $select = this.$el;
+ var value = this.getValue();
+ var multiple = this.get('multiple');
+ var options = {
+ width: '100%',
+ allowClear: this.get('allowNull'),
+ placeholder: this.get('placeholder'),
+ separator: '||',
+ multiple: this.get('multiple'),
+ data: this.getChoices(),
+ escapeMarkup: function( string ){
+ return acf.escHtml( string );
+ },
+ dropdownCss: {
+ 'z-index': '999999999'
+ },
+ initSelection: function( element, callback ) {
+ if( multiple ) {
+ callback( value );
+ } else {
+ callback( value.shift() );
+ }
+ }
+ };
+
+ // get hidden input
+ var $input = $select.siblings('input');
+ if( !$input.length ) {
+ $input = $(' ');
+ $select.before( $input );
+ }
+
+ // set input value
+ inputValue = value.map(function(item){ return item.id }).join('||');
+ $input.val( inputValue );
+
+ // multiple
+ if( options.multiple ) {
+
+ // reorder options
+ value.map(function( item ){
+ item.$el.detach().appendTo( $select );
+ });
+ }
+
+ // remove blank option as we have a clear all button
+ if( options.allowClear ) {
+ options.data = options.data.filter(function(item){
+ return item.id !== '';
+ });
+ }
+
+ // remove conflicting atts
+ $select.removeData('ajax');
+ $select.removeAttr('data-ajax');
+
+ // ajax
+ if( this.get('ajax') ) {
+
+ options.ajax = {
+ url: acf.get('ajaxurl'),
+ quietMillis: 250,
+ dataType: 'json',
+ type: 'post',
+ cache: false,
+ data: $.proxy(this.getAjaxData, this),
+ results: $.proxy(this.processAjaxResults, this),
+ };
+ }
+
+ // filter for 3rd party customization
+ var field = this.get('field');
+ options = acf.applyFilters( 'select2_args', options, $select, this.data, (field || false), this );
+
+ // add select2
+ $input.select2( options );
+
+ // get container
+ var $container = $input.select2('container');
+
+ // helper to find this select's option
+ var getOption = $.proxy(this.getOption, this);
+
+ // multiple
+ if( options.multiple ) {
+
+ // vars
+ var $ul = $container.find('ul');
+
+ // sortable
+ $ul.sortable({
+ stop: function() {
+
+ // loop
+ $ul.find('.select2-search-choice').each(function() {
+
+ // vars
+ var data = $(this).data('select2Data');
+ var $option = getOption( data.id );
+
+ // detach and re-append to end
+ $option.detach().appendTo( $select );
+ });
+
+ // trigger change on input (JS error if trigger on select)
+ $select.trigger('change');
+ }
+ });
+ }
+
+ // on select, create option and move to end
+ $input.on('select2-selecting', function( e ){
+
+ // vars
+ var item = e.choice;
+ var $option = getOption( item.id );
+
+ // create if doesn't exist
+ if( !$option.length ) {
+ $option = $('' + item.text + ' ');
+ }
+
+ // detach and re-append to end
+ $option.detach().appendTo( $select );
+ });
+
+ // add class
+ $container.addClass('-acf');
+
+ // action for 3rd party customization
+ acf.doAction('select2_init', $select, options, this.data, (field || false), this);
+
+ // change
+ $input.on('change', function(){
+ var val = $input.val();
+ if( val.indexOf('||') ) {
+ val = val.split('||');
+ }
+ $select.val( val ).trigger('change');
+ });
+
+ // hide select
+ $select.hide();
+ },
+
+ mergeOptions: function(){
+
+ // vars
+ var $prevOptions = false;
+ var $prevGroup = false;
+
+ // loop
+ $('#select2-drop .select2-result-with-children').each(function(){
+
+ // vars
+ var $options = $(this).children('ul');
+ var $group = $(this).children('.select2-result-label');
+
+ // compare to previous
+ if( $prevGroup && $prevGroup.text() === $group.text() ) {
+ $prevGroup.append( $options.children() );
+ $(this).remove();
+ return;
+ }
+
+ // update vars
+ $prevOptions = $options;
+ $prevGroup = $group;
+
+ });
+
+ },
+
+ getAjaxData: function( term, page ){
+
+ // create Select2 v4 params
+ var params = {
+ term: term,
+ page: page
+ }
+
+ // return
+ return Select2.prototype.getAjaxData.apply(this, [params]);
+ },
+
+ });
+
+
+ // manager
+ var select2Manager = new acf.Model({
+ priority: 5,
+ wait: 'prepare',
+ actions: {
+ 'duplicate': 'onDuplicate'
+ },
+ initialize: function(){
+
+ // vars
+ var locale = acf.get('locale');
+ var rtl = acf.get('rtl');
+ var l10n = acf.get('select2L10n');
+ var version = getVersion();
+
+ // bail ealry if no l10n
+ if( !l10n ) {
+ return false;
+ }
+
+ // bail early if 'en'
+ if( locale.indexOf('en') === 0 ) {
+ return false;
+ }
+
+ // initialize
+ if( version == 4 ) {
+ this.addTranslations4();
+ } else if( version == 3 ) {
+ this.addTranslations3();
+ }
+ },
+
+ addTranslations4: function(){
+
+ // vars
+ var l10n = acf.get('select2L10n');
+ var locale = acf.get('locale');
+
+ // modify local to match html[lang] attribute (used by Select2)
+ locale = locale.replace('_', '-');
+
+ // select2L10n
+ var select2L10n = {
+ errorLoading: function () {
+ return l10n.load_fail;
+ },
+ inputTooLong: function (args) {
+ var overChars = args.input.length - args.maximum;
+ if( overChars > 1 ) {
+ return l10n.input_too_long_n.replace( '%d', overChars );
+ }
+ return l10n.input_too_long_1;
+ },
+ inputTooShort: function( args ){
+ var remainingChars = args.minimum - args.input.length;
+ if( remainingChars > 1 ) {
+ return l10n.input_too_short_n.replace( '%d', remainingChars );
+ }
+ return l10n.input_too_short_1;
+ },
+ loadingMore: function () {
+ return l10n.load_more;
+ },
+ maximumSelected: function( args ) {
+ var maximum = args.maximum;
+ if( maximum > 1 ) {
+ return l10n.selection_too_long_n.replace( '%d', maximum );
+ }
+ return l10n.selection_too_long_1;
+ },
+ noResults: function () {
+ return l10n.matches_0;
+ },
+ searching: function () {
+ return l10n.searching;
+ }
+ };
+
+ // append
+ jQuery.fn.select2.amd.define('select2/i18n/' + locale, [], function(){
+ return select2L10n;
+ });
+ },
+
+ addTranslations3: function(){
+
+ // vars
+ var l10n = acf.get('select2L10n');
+ var locale = acf.get('locale');
+
+ // modify local to match html[lang] attribute (used by Select2)
+ locale = locale.replace('_', '-');
+
+ // select2L10n
+ var select2L10n = {
+ formatMatches: function( matches ) {
+ if( matches > 1 ) {
+ return l10n.matches_n.replace( '%d', matches );
+ }
+ return l10n.matches_1;
+ },
+ formatNoMatches: function() {
+ return l10n.matches_0;
+ },
+ formatAjaxError: function() {
+ return l10n.load_fail;
+ },
+ formatInputTooShort: function( input, min ) {
+ var remainingChars = min - input.length;
+ if( remainingChars > 1 ) {
+ return l10n.input_too_short_n.replace( '%d', remainingChars );
+ }
+ return l10n.input_too_short_1;
+ },
+ formatInputTooLong: function( input, max ) {
+ var overChars = input.length - max;
+ if( overChars > 1 ) {
+ return l10n.input_too_long_n.replace( '%d', overChars );
+ }
+ return l10n.input_too_long_1;
+ },
+ formatSelectionTooBig: function( maximum ) {
+ if( maximum > 1 ) {
+ return l10n.selection_too_long_n.replace( '%d', maximum );
+ }
+ return l10n.selection_too_long_1;
+ },
+ formatLoadMore: function() {
+ return l10n.load_more;
+ },
+ formatSearching: function() {
+ return l10n.searching;
+ }
+ };
+
+ // ensure locales exists
+ $.fn.select2.locales = $.fn.select2.locales || {};
+
+ // append
+ $.fn.select2.locales[ locale ] = select2L10n;
+ $.extend($.fn.select2.defaults, select2L10n);
+ },
+
+ onDuplicate: function( $el, $el2 ){
+ $el2.find('.select2-container').remove();
+ }
+
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- acf.tinymce = {
- /*
- * defaults
- *
- * This function will return default mce and qt settings
- *
- * @type function
- * @date 18/8/17
- * @since 5.6.0
- *
- * @param $post_id (int)
- * @return $post_id (int)
- */
- defaults: function () {
- // bail early if no tinyMCEPreInit
- if (typeof tinyMCEPreInit === 'undefined') return false; // vars
-
- var defaults = {
- tinymce: tinyMCEPreInit.mceInit.acf_content,
- quicktags: tinyMCEPreInit.qtInit.acf_content
- }; // return
-
- return defaults;
- },
-
- /*
- * initialize
- *
- * This function will initialize the tinymce and quicktags instances
- *
- * @type function
- * @date 18/8/17
- * @since 5.6.0
- *
- * @param $post_id (int)
- * @return $post_id (int)
- */
- initialize: function (id, args) {
- // defaults
- args = acf.parseArgs(args, {
- tinymce: true,
- quicktags: true,
- toolbar: 'full',
- mode: 'visual',
- // visual,text
- field: false
- }); // tinymce
-
- if (args.tinymce) {
- this.initializeTinymce(id, args);
- } // quicktags
-
-
- if (args.quicktags) {
- this.initializeQuicktags(id, args);
- }
- },
-
- /*
- * initializeTinymce
- *
- * This function will initialize the tinymce instance
- *
- * @type function
- * @date 18/8/17
- * @since 5.6.0
- *
- * @param $post_id (int)
- * @return $post_id (int)
- */
- initializeTinymce: function (id, args) {
- // vars
- var $textarea = $('#' + id);
- var defaults = this.defaults();
- var toolbars = acf.get('toolbars');
- var field = args.field || false;
- var $field = field.$el || false; // bail early
-
- if (typeof tinymce === 'undefined') return false;
- if (!defaults) return false; // check if exists
-
- if (tinymce.get(id)) {
- return this.enable(id);
- } // settings
-
-
- var init = $.extend({}, defaults.tinymce, args.tinymce);
- init.id = id;
- init.selector = '#' + id; // toolbar
-
- var toolbar = args.toolbar;
-
- if (toolbar && toolbars && toolbars[toolbar]) {
- for (var i = 1; i <= 4; i++) {
- init['toolbar' + i] = toolbars[toolbar][i] || '';
- }
- } // event
-
-
- init.setup = function (ed) {
- ed.on('change', function (e) {
- ed.save(); // save to textarea
-
- $textarea.trigger('change');
- }); // Fix bug where Gutenberg does not hear "mouseup" event and tries to select multiple blocks.
-
- ed.on('mouseup', function (e) {
- var event = new MouseEvent('mouseup');
- window.dispatchEvent(event);
- }); // Temporarily comment out. May not be necessary due to wysiwyg field actions.
- //ed.on('unload', function(e) {
- // acf.tinymce.remove( id );
- //});
- }; // disable wp_autoresize_on (no solution yet for fixed toolbar)
-
-
- init.wp_autoresize_on = false; // Enable wpautop allowing value to save without tags.
- // Only if the "TinyMCE Advanced" plugin hasn't already set this functionality.
-
- if (!init.tadv_noautop) {
- init.wpautop = true;
- } // hook for 3rd party customization
-
-
- init = acf.applyFilters('wysiwyg_tinymce_settings', init, id, field); // z-index fix (caused too many conflicts)
- //if( acf.isset(tinymce,'ui','FloatPanel') ) {
- // tinymce.ui.FloatPanel.zIndex = 900000;
- //}
- // store settings
-
- tinyMCEPreInit.mceInit[id] = init; // visual tab is active
-
- if (args.mode == 'visual') {
- // init
- var result = tinymce.init(init); // get editor
-
- var ed = tinymce.get(id); // validate
-
- if (!ed) {
- return false;
- } // add reference
-
-
- ed.acf = args.field; // action
-
- acf.doAction('wysiwyg_tinymce_init', ed, ed.id, init, field);
- }
- },
-
- /*
- * initializeQuicktags
- *
- * This function will initialize the quicktags instance
- *
- * @type function
- * @date 18/8/17
- * @since 5.6.0
- *
- * @param $post_id (int)
- * @return $post_id (int)
- */
- initializeQuicktags: function (id, args) {
- // vars
- var defaults = this.defaults(); // bail early
-
- if (typeof quicktags === 'undefined') return false;
- if (!defaults) return false; // settings
-
- var init = $.extend({}, defaults.quicktags, args.quicktags);
- init.id = id; // filter
-
- var field = args.field || false;
- var $field = field.$el || false;
- init = acf.applyFilters('wysiwyg_quicktags_settings', init, init.id, field); // store settings
-
- tinyMCEPreInit.qtInit[id] = init; // init
-
- var ed = quicktags(init); // validate
-
- if (!ed) {
- return false;
- } // generate HTML
-
-
- this.buildQuicktags(ed); // action for 3rd party customization
-
- acf.doAction('wysiwyg_quicktags_init', ed, ed.id, init, field);
- },
-
- /*
- * buildQuicktags
- *
- * This function will build the quicktags HTML
- *
- * @type function
- * @date 18/8/17
- * @since 5.6.0
- *
- * @param $post_id (int)
- * @return $post_id (int)
- */
- buildQuicktags: function (ed) {
- var canvas,
- name,
- settings,
- theButtons,
- html,
- ed,
- id,
- i,
- use,
- instanceId,
- defaults = ',strong,em,link,block,del,ins,img,ul,ol,li,code,more,close,';
- canvas = ed.canvas;
- name = ed.name;
- settings = ed.settings;
- html = '';
- theButtons = {};
- use = '';
- instanceId = ed.id; // set buttons
-
- if (settings.buttons) {
- use = ',' + settings.buttons + ',';
- }
-
- for (i in edButtons) {
- if (!edButtons[i]) {
- continue;
- }
-
- id = edButtons[i].id;
-
- if (use && defaults.indexOf(',' + id + ',') !== -1 && use.indexOf(',' + id + ',') === -1) {
- continue;
- }
-
- if (!edButtons[i].instance || edButtons[i].instance === instanceId) {
- theButtons[id] = edButtons[i];
-
- if (edButtons[i].html) {
- html += edButtons[i].html(name + '_');
- }
- }
- }
-
- if (use && use.indexOf(',dfw,') !== -1) {
- theButtons.dfw = new QTags.DFWButton();
- html += theButtons.dfw.html(name + '_');
- }
-
- if ('rtl' === document.getElementsByTagName('html')[0].dir) {
- theButtons.textdirection = new QTags.TextDirectionButton();
- html += theButtons.textdirection.html(name + '_');
- }
-
- ed.toolbar.innerHTML = html;
- ed.theButtons = theButtons;
-
- if (typeof jQuery !== 'undefined') {
- jQuery(document).triggerHandler('quicktags-init', [ed]);
- }
- },
- disable: function (id) {
- this.destroyTinymce(id);
- },
- remove: function (id) {
- this.destroyTinymce(id);
- },
- destroy: function (id) {
- this.destroyTinymce(id);
- },
- destroyTinymce: function (id) {
- // bail early
- if (typeof tinymce === 'undefined') return false; // get editor
-
- var ed = tinymce.get(id); // bail early if no editor
-
- if (!ed) return false; // save
-
- ed.save(); // destroy editor
-
- ed.destroy(); // return
-
- return true;
- },
- enable: function (id) {
- this.enableTinymce(id);
- },
- enableTinymce: function (id) {
- // bail early
- if (typeof switchEditors === 'undefined') return false; // bail ealry if not initialized
-
- if (typeof tinyMCEPreInit.mceInit[id] === 'undefined') return false; // Ensure textarea element is visible
- // - Fixes bug in block editor when switching between "Block" and "Document" tabs.
-
- $('#' + id).show(); // toggle
-
- switchEditors.go(id, 'tmce'); // return
-
- return true;
- }
- };
- var editorManager = new acf.Model({
- // hook in before fieldsEventManager, conditions, etc
- priority: 5,
- actions: {
- 'prepare': 'onPrepare',
- 'ready': 'onReady'
- },
- onPrepare: function () {
- // find hidden editor which may exist within a field
- var $div = $('#acf-hidden-wp-editor'); // move to footer
-
- if ($div.exists()) {
- $div.appendTo('body');
- }
- },
- onReady: function () {
- // Restore wp.editor functions used by tinymce removed in WP5.
- if (acf.isset(window, 'wp', 'oldEditor')) {
- wp.editor.autop = wp.oldEditor.autop;
- wp.editor.removep = wp.oldEditor.removep;
- } // bail early if no tinymce
-
-
- if (!acf.isset(window, 'tinymce', 'on')) return; // restore default activeEditor
-
- tinymce.on('AddEditor', function (data) {
- // vars
- var editor = data.editor; // bail early if not 'acf'
-
- if (editor.id.substr(0, 3) !== 'acf') return; // override if 'content' exists
-
- editor = tinymce.editors.content || editor; // update vars
-
- tinymce.activeEditor = editor;
- wpActiveEditor = editor.id;
- });
- }
- });
+(function($, undefined){
+
+ acf.tinymce = {
+
+ /*
+ * defaults
+ *
+ * This function will return default mce and qt settings
+ *
+ * @type function
+ * @date 18/8/17
+ * @since 5.6.0
+ *
+ * @param $post_id (int)
+ * @return $post_id (int)
+ */
+
+ defaults: function(){
+
+ // bail early if no tinyMCEPreInit
+ if( typeof tinyMCEPreInit === 'undefined' ) return false;
+
+ // vars
+ var defaults = {
+ tinymce: tinyMCEPreInit.mceInit.acf_content,
+ quicktags: tinyMCEPreInit.qtInit.acf_content
+ };
+
+ // return
+ return defaults;
+ },
+
+
+ /*
+ * initialize
+ *
+ * This function will initialize the tinymce and quicktags instances
+ *
+ * @type function
+ * @date 18/8/17
+ * @since 5.6.0
+ *
+ * @param $post_id (int)
+ * @return $post_id (int)
+ */
+
+ initialize: function( id, args ){
+
+ // defaults
+ args = acf.parseArgs(args, {
+ tinymce: true,
+ quicktags: true,
+ toolbar: 'full',
+ mode: 'visual', // visual,text
+ field: false
+ });
+
+ // tinymce
+ if( args.tinymce ) {
+ this.initializeTinymce( id, args );
+ }
+
+ // quicktags
+ if( args.quicktags ) {
+ this.initializeQuicktags( id, args );
+ }
+ },
+
+
+ /*
+ * initializeTinymce
+ *
+ * This function will initialize the tinymce instance
+ *
+ * @type function
+ * @date 18/8/17
+ * @since 5.6.0
+ *
+ * @param $post_id (int)
+ * @return $post_id (int)
+ */
+
+ initializeTinymce: function( id, args ){
+
+ // vars
+ var $textarea = $('#'+id);
+ var defaults = this.defaults();
+ var toolbars = acf.get('toolbars');
+ var field = args.field || false;
+ var $field = field.$el || false;
+
+ // bail early
+ if( typeof tinymce === 'undefined' ) return false;
+ if( !defaults ) return false;
+
+ // check if exists
+ if( tinymce.get(id) ) {
+ return this.enable( id );
+ }
+
+ // settings
+ var init = $.extend( {}, defaults.tinymce, args.tinymce );
+ init.id = id;
+ init.selector = '#' + id;
+
+ // toolbar
+ var toolbar = args.toolbar;
+ if( toolbar && toolbars && toolbars[toolbar] ) {
+
+ for( var i = 1; i <= 4; i++ ) {
+ init[ 'toolbar' + i ] = toolbars[toolbar][i] || '';
+ }
+ }
+
+ // event
+ init.setup = function( ed ){
+
+ ed.on('change', function(e) {
+ ed.save(); // save to textarea
+ $textarea.trigger('change');
+ });
+
+ // Fix bug where Gutenberg does not hear "mouseup" event and tries to select multiple blocks.
+ ed.on('mouseup', function(e) {
+ var event = new MouseEvent('mouseup');
+ window.dispatchEvent(event);
+ });
+
+ // Temporarily comment out. May not be necessary due to wysiwyg field actions.
+ //ed.on('unload', function(e) {
+ // acf.tinymce.remove( id );
+ //});
+ };
+
+ // disable wp_autoresize_on (no solution yet for fixed toolbar)
+ init.wp_autoresize_on = false;
+
+ // Enable wpautop allowing value to save without
tags.
+ // Only if the "TinyMCE Advanced" plugin hasn't already set this functionality.
+ if( !init.tadv_noautop ) {
+ init.wpautop = true;
+ }
+
+ // hook for 3rd party customization
+ init = acf.applyFilters('wysiwyg_tinymce_settings', init, id, field);
+
+ // z-index fix (caused too many conflicts)
+ //if( acf.isset(tinymce,'ui','FloatPanel') ) {
+ // tinymce.ui.FloatPanel.zIndex = 900000;
+ //}
+
+ // store settings
+ tinyMCEPreInit.mceInit[ id ] = init;
+
+ // visual tab is active
+ if( args.mode == 'visual' ) {
+
+ // init
+ var result = tinymce.init( init );
+
+ // get editor
+ var ed = tinymce.get( id );
+
+ // validate
+ if( !ed ) {
+ return false;
+ }
+
+ // add reference
+ ed.acf = args.field;
+
+ // action
+ acf.doAction('wysiwyg_tinymce_init', ed, ed.id, init, field);
+ }
+ },
+
+ /*
+ * initializeQuicktags
+ *
+ * This function will initialize the quicktags instance
+ *
+ * @type function
+ * @date 18/8/17
+ * @since 5.6.0
+ *
+ * @param $post_id (int)
+ * @return $post_id (int)
+ */
+
+ initializeQuicktags: function( id, args ){
+
+ // vars
+ var defaults = this.defaults();
+
+ // bail early
+ if( typeof quicktags === 'undefined' ) return false;
+ if( !defaults ) return false;
+
+ // settings
+ var init = $.extend( {}, defaults.quicktags, args.quicktags );
+ init.id = id;
+
+ // filter
+ var field = args.field || false;
+ var $field = field.$el || false;
+ init = acf.applyFilters('wysiwyg_quicktags_settings', init, init.id, field);
+
+ // store settings
+ tinyMCEPreInit.qtInit[ id ] = init;
+
+ // init
+ var ed = quicktags( init );
+
+ // validate
+ if( !ed ) {
+ return false;
+ }
+
+ // generate HTML
+ this.buildQuicktags( ed );
+
+ // action for 3rd party customization
+ acf.doAction('wysiwyg_quicktags_init', ed, ed.id, init, field);
+ },
+
+
+ /*
+ * buildQuicktags
+ *
+ * This function will build the quicktags HTML
+ *
+ * @type function
+ * @date 18/8/17
+ * @since 5.6.0
+ *
+ * @param $post_id (int)
+ * @return $post_id (int)
+ */
+
+ buildQuicktags: function( ed ){
+
+ var canvas, name, settings, theButtons, html, ed, id, i, use, instanceId,
+ defaults = ',strong,em,link,block,del,ins,img,ul,ol,li,code,more,close,';
+
+ canvas = ed.canvas;
+ name = ed.name;
+ settings = ed.settings;
+ html = '';
+ theButtons = {};
+ use = '';
+ instanceId = ed.id;
+
+ // set buttons
+ if ( settings.buttons ) {
+ use = ','+settings.buttons+',';
+ }
+
+ for ( i in edButtons ) {
+ if ( ! edButtons[i] ) {
+ continue;
+ }
+
+ id = edButtons[i].id;
+ if ( use && defaults.indexOf( ',' + id + ',' ) !== -1 && use.indexOf( ',' + id + ',' ) === -1 ) {
+ continue;
+ }
+
+ if ( ! edButtons[i].instance || edButtons[i].instance === instanceId ) {
+ theButtons[id] = edButtons[i];
+
+ if ( edButtons[i].html ) {
+ html += edButtons[i].html( name + '_' );
+ }
+ }
+ }
+
+ if ( use && use.indexOf(',dfw,') !== -1 ) {
+ theButtons.dfw = new QTags.DFWButton();
+ html += theButtons.dfw.html( name + '_' );
+ }
+
+ if ( 'rtl' === document.getElementsByTagName( 'html' )[0].dir ) {
+ theButtons.textdirection = new QTags.TextDirectionButton();
+ html += theButtons.textdirection.html( name + '_' );
+ }
+
+ ed.toolbar.innerHTML = html;
+ ed.theButtons = theButtons;
+
+ if ( typeof jQuery !== 'undefined' ) {
+ jQuery( document ).triggerHandler( 'quicktags-init', [ ed ] );
+ }
+
+ },
+
+ disable: function( id ){
+ this.destroyTinymce( id );
+ },
+
+ remove: function( id ){
+ this.destroyTinymce( id );
+ },
+
+ destroy: function( id ){
+ this.destroyTinymce( id );
+ },
+
+ destroyTinymce: function( id ){
+
+ // bail early
+ if( typeof tinymce === 'undefined' ) return false;
+
+ // get editor
+ var ed = tinymce.get( id );
+
+ // bail early if no editor
+ if( !ed ) return false;
+
+ // save
+ ed.save();
+
+ // destroy editor
+ ed.destroy();
+
+ // return
+ return true;
+ },
+
+ enable: function( id ){
+ this.enableTinymce( id );
+ },
+
+ enableTinymce: function( id ){
+
+ // bail early
+ if( typeof switchEditors === 'undefined' ) return false;
+
+ // bail ealry if not initialized
+ if( typeof tinyMCEPreInit.mceInit[ id ] === 'undefined' ) return false;
+
+ // Ensure textarea element is visible
+ // - Fixes bug in block editor when switching between "Block" and "Document" tabs.
+ $('#'+id).show();
+
+ // toggle
+ switchEditors.go( id, 'tmce');
+
+ // return
+ return true;
+ }
+ };
+
+ var editorManager = new acf.Model({
+
+ // hook in before fieldsEventManager, conditions, etc
+ priority: 5,
+
+ actions: {
+ 'prepare': 'onPrepare',
+ 'ready': 'onReady',
+ },
+ onPrepare: function(){
+
+ // find hidden editor which may exist within a field
+ var $div = $('#acf-hidden-wp-editor');
+
+ // move to footer
+ if( $div.exists() ) {
+ $div.appendTo('body');
+ }
+ },
+ onReady: function(){
+
+ // Restore wp.editor functions used by tinymce removed in WP5.
+ if( acf.isset(window,'wp','oldEditor') ) {
+ wp.editor.autop = wp.oldEditor.autop;
+ wp.editor.removep = wp.oldEditor.removep;
+ }
+
+ // bail early if no tinymce
+ if( !acf.isset(window,'tinymce','on') ) return;
+
+ // restore default activeEditor
+ tinymce.on('AddEditor', function( data ){
+
+ // vars
+ var editor = data.editor;
+
+ // bail early if not 'acf'
+ if( editor.id.substr(0, 3) !== 'acf' ) return;
+
+ // override if 'content' exists
+ editor = tinymce.editors.content || editor;
+
+ // update vars
+ tinymce.activeEditor = editor;
+ wpActiveEditor = editor.id;
+ });
+ }
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- /**
- * Validator
- *
- * The model for validating forms
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- var Validator = acf.Model.extend({
- /** @var string The model identifier. */
- id: 'Validator',
-
- /** @var object The model data. */
- data: {
- /** @var array The form errors. */
- errors: [],
-
- /** @var object The form notice. */
- notice: null,
-
- /** @var string The form status. loading, invalid, valid */
- status: ''
- },
-
- /** @var object The model events. */
- events: {
- 'changed:status': 'onChangeStatus'
- },
-
- /**
- * addErrors
- *
- * Adds errors to the form.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param array errors An array of errors.
- * @return void
- */
- addErrors: function (errors) {
- errors.map(this.addError, this);
- },
-
- /**
- * addError
- *
- * Adds and error to the form.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object error An error object containing input and message.
- * @return void
- */
- addError: function (error) {
- this.data.errors.push(error);
- },
-
- /**
- * hasErrors
- *
- * Returns true if the form has errors.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return bool
- */
- hasErrors: function () {
- return this.data.errors.length;
- },
-
- /**
- * clearErrors
- *
- * Removes any errors.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- clearErrors: function () {
- return this.data.errors = [];
- },
-
- /**
- * getErrors
- *
- * Returns the forms errors.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return array
- */
- getErrors: function () {
- return this.data.errors;
- },
-
- /**
- * getFieldErrors
- *
- * Returns the forms field errors.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return array
- */
- getFieldErrors: function () {
- // vars
- var errors = [];
- var inputs = []; // loop
-
- this.getErrors().map(function (error) {
- // bail early if global
- if (!error.input) return; // update if exists
-
- var i = inputs.indexOf(error.input);
-
- if (i > -1) {
- errors[i] = error; // update
- } else {
- errors.push(error);
- inputs.push(error.input);
- }
- }); // return
-
- return errors;
- },
-
- /**
- * getGlobalErrors
- *
- * Returns the forms global errors (errors without a specific input).
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return array
- */
- getGlobalErrors: function () {
- // return array of errors that contain no input
- return this.getErrors().filter(function (error) {
- return !error.input;
- });
- },
-
- /**
- * showErrors
- *
- * Displays all errors for this form.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- showErrors: function () {
- // bail early if no errors
- if (!this.hasErrors()) {
- return;
- } // vars
-
-
- var fieldErrors = this.getFieldErrors();
- var globalErrors = this.getGlobalErrors(); // vars
-
- var errorCount = 0;
- var $scrollTo = false; // loop
-
- fieldErrors.map(function (error) {
- // get input
- var $input = this.$('[name="' + error.input + '"]').first(); // if $_POST value was an array, this $input may not exist
-
- if (!$input.length) {
- $input = this.$('[name^="' + error.input + '"]').first();
- } // bail early if input doesn't exist
-
-
- if (!$input.length) {
- return;
- } // increase
-
-
- errorCount++; // get field
-
- var field = acf.getClosestField($input); // show error
-
- field.showError(error.message); // set $scrollTo
-
- if (!$scrollTo) {
- $scrollTo = field.$el;
- }
- }, this); // errorMessage
-
- var errorMessage = acf.__('Validation failed');
-
- globalErrors.map(function (error) {
- errorMessage += '. ' + error.message;
- });
-
- if (errorCount == 1) {
- errorMessage += '. ' + acf.__('1 field requires attention');
- } else if (errorCount > 1) {
- errorMessage += '. ' + acf.__('%d fields require attention').replace('%d', errorCount);
- } // notice
-
-
- if (this.has('notice')) {
- this.get('notice').update({
- type: 'error',
- text: errorMessage
- });
- } else {
- var notice = acf.newNotice({
- type: 'error',
- text: errorMessage,
- target: this.$el
- });
- this.set('notice', notice);
- } // if no $scrollTo, set to message
-
-
- if (!$scrollTo) {
- $scrollTo = this.get('notice').$el;
- } // timeout
-
-
- setTimeout(function () {
- $("html, body").animate({
- scrollTop: $scrollTo.offset().top - $(window).height() / 2
- }, 500);
- }, 10);
- },
-
- /**
- * onChangeStatus
- *
- * Update the form class when changing the 'status' data
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object e The event object.
- * @param jQuery $el The form element.
- * @param string value The new status.
- * @param string prevValue The old status.
- * @return void
- */
- onChangeStatus: function (e, $el, value, prevValue) {
- this.$el.removeClass('is-' + prevValue).addClass('is-' + value);
- },
-
- /**
- * validate
- *
- * Vaildates the form via AJAX.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object args A list of settings to customize the validation process.
- * @return bool True if the form is valid.
- */
- validate: function (args) {
- // default args
- args = acf.parseArgs(args, {
- // trigger event
- event: false,
- // reset the form after submit
- reset: false,
- // loading callback
- loading: function () {},
- // complete callback
- complete: function () {},
- // failure callback
- failure: function () {},
- // success callback
- success: function ($form) {
- $form.submit();
- }
- }); // return true if is valid - allows form submit
-
- if (this.get('status') == 'valid') {
- return true;
- } // return false if is currently validating - prevents form submit
-
-
- if (this.get('status') == 'validating') {
- return false;
- } // return true if no ACF fields exist (no need to validate)
-
-
- if (!this.$('.acf-field').length) {
- return true;
- } // if event is provided, create a new success callback.
-
-
- if (args.event) {
- var event = $.Event(null, args.event);
-
- args.success = function () {
- acf.enableSubmit($(event.target)).trigger(event);
- };
- } // action for 3rd party
-
-
- acf.doAction('validation_begin', this.$el); // lock form
-
- acf.lockForm(this.$el); // loading callback
-
- args.loading(this.$el, this); // update status
-
- this.set('status', 'validating'); // success callback
-
- var onSuccess = function (json) {
- // validate
- if (!acf.isAjaxSuccess(json)) {
- return;
- } // filter
-
-
- var data = acf.applyFilters('validation_complete', json.data, this.$el, this); // add errors
-
- if (!data.valid) {
- this.addErrors(data.errors);
- }
- }; // complete
-
-
- var onComplete = function () {
- // unlock form
- acf.unlockForm(this.$el); // failure
-
- if (this.hasErrors()) {
- // update status
- this.set('status', 'invalid'); // action
-
- acf.doAction('validation_failure', this.$el, this); // display errors
-
- this.showErrors(); // failure callback
-
- args.failure(this.$el, this); // success
- } else {
- // update status
- this.set('status', 'valid'); // remove previous error message
-
- if (this.has('notice')) {
- this.get('notice').update({
- type: 'success',
- text: acf.__('Validation successful'),
- timeout: 1000
- });
- } // action
-
-
- acf.doAction('validation_success', this.$el, this);
- acf.doAction('submit', this.$el); // success callback (submit form)
-
- args.success(this.$el, this); // lock form
-
- acf.lockForm(this.$el); // reset
-
- if (args.reset) {
- this.reset();
- }
- } // complete callback
-
-
- args.complete(this.$el, this); // clear errors
-
- this.clearErrors();
- }; // serialize form data
-
-
- var data = acf.serialize(this.$el);
- data.action = 'acf/validate_save_post'; // ajax
-
- $.ajax({
- url: acf.get('ajaxurl'),
- data: acf.prepareForAjax(data),
- type: 'post',
- dataType: 'json',
- context: this,
- success: onSuccess,
- complete: onComplete
- }); // return false to fail validation and allow AJAX
-
- return false;
- },
-
- /**
- * setup
- *
- * Called during the constructor function to setup this instance
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $form The form element.
- * @return void
- */
- setup: function ($form) {
- // set $el
- this.$el = $form;
- },
-
- /**
- * reset
- *
- * Rests the validation to be used again.
- *
- * @date 6/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- reset: function () {
- // reset data
- this.set('errors', []);
- this.set('notice', null);
- this.set('status', ''); // unlock form
-
- acf.unlockForm(this.$el);
- }
- });
- /**
- * getValidator
- *
- * Returns the instance for a given form element.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $el The form element.
- * @return object
- */
-
- var getValidator = function ($el) {
- // instantiate
- var validator = $el.data('acf');
-
- if (!validator) {
- validator = new Validator($el);
- } // return
-
-
- return validator;
- };
- /**
- * acf.validateForm
- *
- * A helper function for the Validator.validate() function.
- * Returns true if form is valid, or fetches a validation request and returns false.
- *
- * @date 4/4/18
- * @since 5.6.9
- *
- * @param object args A list of settings to customize the validation process.
- * @return bool
- */
-
-
- acf.validateForm = function (args) {
- return getValidator(args.form).validate(args);
- };
- /**
- * acf.enableSubmit
- *
- * Enables a submit button and returns the element.
- *
- * @date 30/8/18
- * @since 5.7.4
- *
- * @param jQuery $submit The submit button.
- * @return jQuery
- */
-
-
- acf.enableSubmit = function ($submit) {
- return $submit.removeClass('disabled');
- };
- /**
- * acf.disableSubmit
- *
- * Disables a submit button and returns the element.
- *
- * @date 30/8/18
- * @since 5.7.4
- *
- * @param jQuery $submit The submit button.
- * @return jQuery
- */
-
-
- acf.disableSubmit = function ($submit) {
- return $submit.addClass('disabled');
- };
- /**
- * acf.showSpinner
- *
- * Shows the spinner element.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $spinner The spinner element.
- * @return jQuery
- */
-
-
- acf.showSpinner = function ($spinner) {
- $spinner.addClass('is-active'); // add class (WP > 4.2)
-
- $spinner.css('display', 'inline-block'); // css (WP < 4.2)
-
- return $spinner;
- };
- /**
- * acf.hideSpinner
- *
- * Hides the spinner element.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $spinner The spinner element.
- * @return jQuery
- */
-
-
- acf.hideSpinner = function ($spinner) {
- $spinner.removeClass('is-active'); // add class (WP > 4.2)
-
- $spinner.css('display', 'none'); // css (WP < 4.2)
-
- return $spinner;
- };
- /**
- * acf.lockForm
- *
- * Locks a form by disabeling its primary inputs and showing a spinner.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $form The form element.
- * @return jQuery
- */
-
-
- acf.lockForm = function ($form) {
- // vars
- var $wrap = findSubmitWrap($form);
- var $submit = $wrap.find('.button, [type="submit"]');
- var $spinner = $wrap.find('.spinner, .acf-spinner'); // hide all spinners (hides the preview spinner)
-
- acf.hideSpinner($spinner); // lock
-
- acf.disableSubmit($submit);
- acf.showSpinner($spinner.last());
- return $form;
- };
- /**
- * acf.unlockForm
- *
- * Unlocks a form by enabeling its primary inputs and hiding all spinners.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $form The form element.
- * @return jQuery
- */
-
-
- acf.unlockForm = function ($form) {
- // vars
- var $wrap = findSubmitWrap($form);
- var $submit = $wrap.find('.button, [type="submit"]');
- var $spinner = $wrap.find('.spinner, .acf-spinner'); // unlock
-
- acf.enableSubmit($submit);
- acf.hideSpinner($spinner);
- return $form;
- };
- /**
- * findSubmitWrap
- *
- * An internal function to find the 'primary' form submit wrapping element.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $form The form element.
- * @return jQuery
- */
-
-
- var findSubmitWrap = function ($form) {
- // default post submit div
- var $wrap = $form.find('#submitdiv');
-
- if ($wrap.length) {
- return $wrap;
- } // 3rd party publish box
-
-
- var $wrap = $form.find('#submitpost');
-
- if ($wrap.length) {
- return $wrap;
- } // term, user
-
-
- var $wrap = $form.find('p.submit').last();
-
- if ($wrap.length) {
- return $wrap;
- } // front end form
-
-
- var $wrap = $form.find('.acf-form-submit');
-
- if ($wrap.length) {
- return $wrap;
- } // default
-
-
- return $form;
- };
- /**
- * A debounced function to trigger a form submission.
- *
- * @date 15/07/2020
- * @since 5.9.0
- *
- * @param type Var Description.
- * @return type Description.
- */
-
-
- var submitFormDebounced = acf.debounce(function ($form) {
- $form.submit();
- });
- /**
- * acf.validation
- *
- * Global validation logic
- *
- * @date 4/4/18
- * @since 5.6.9
- *
- * @param void
- * @return void
- */
-
- acf.validation = new acf.Model({
- /** @var string The model identifier. */
- id: 'validation',
-
- /** @var bool The active state. Set to false before 'prepare' to prevent validation. */
- active: true,
-
- /** @var string The model initialize time. */
- wait: 'prepare',
-
- /** @var object The model actions. */
- actions: {
- 'ready': 'addInputEvents',
- 'append': 'addInputEvents'
- },
-
- /** @var object The model events. */
- events: {
- 'click input[type="submit"]': 'onClickSubmit',
- 'click button[type="submit"]': 'onClickSubmit',
- //'click #editor .editor-post-publish-button': 'onClickSubmitGutenberg',
- 'click #save-post': 'onClickSave',
- 'submit form#post': 'onSubmitPost',
- 'submit form': 'onSubmit'
- },
-
- /**
- * initialize
- *
- * Called when initializing the model.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- initialize: function () {
- // check 'validation' setting
- if (!acf.get('validation')) {
- this.active = false;
- this.actions = {};
- this.events = {};
- }
- },
-
- /**
- * enable
- *
- * Enables validation.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- enable: function () {
- this.active = true;
- },
-
- /**
- * disable
- *
- * Disables validation.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param void
- * @return void
- */
- disable: function () {
- this.active = false;
- },
-
- /**
- * reset
- *
- * Rests the form validation to be used again
- *
- * @date 6/9/18
- * @since 5.7.5
- *
- * @param jQuery $form The form element.
- * @return void
- */
- reset: function ($form) {
- getValidator($form).reset();
- },
-
- /**
- * addInputEvents
- *
- * Adds 'invalid' event listeners to HTML inputs.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param jQuery $el The element being added / readied.
- * @return void
- */
- addInputEvents: function ($el) {
- // Bug exists in Safari where custom "invalid" handeling prevents draft from saving.
- if (acf.get('browser') === 'safari') return; // vars
-
- var $inputs = $('.acf-field [name]', $el); // check
-
- if ($inputs.length) {
- this.on($inputs, 'invalid', 'onInvalid');
- }
- },
-
- /**
- * onInvalid
- *
- * Callback for the 'invalid' event.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object e The event object.
- * @param jQuery $el The input element.
- * @return void
- */
- onInvalid: function (e, $el) {
- // prevent default
- // - prevents browser error message
- // - also fixes chrome bug where 'hidden-by-tab' field throws focus error
- e.preventDefault(); // vars
-
- var $form = $el.closest('form'); // check form exists
-
- if ($form.length) {
- // add error to validator
- getValidator($form).addError({
- input: $el.attr('name'),
- message: acf.strEscape(e.target.validationMessage)
- }); // trigger submit on $form
- // - allows for "save", "preview" and "publish" to work
-
- submitFormDebounced($form);
- }
- },
-
- /**
- * onClickSubmit
- *
- * Callback when clicking submit.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object e The event object.
- * @param jQuery $el The input element.
- * @return void
- */
- onClickSubmit: function (e, $el) {
- // store the "click event" for later use in this.onSubmit()
- this.set('originalEvent', e);
- },
-
- /**
- * onClickSave
- *
- * Set ignore to true when saving a draft.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object e The event object.
- * @param jQuery $el The input element.
- * @return void
- */
- onClickSave: function (e, $el) {
- this.set('ignore', true);
- },
-
- /**
- * onClickSubmitGutenberg
- *
- * Custom validation event for the gutenberg editor.
- *
- * @date 29/10/18
- * @since 5.8.0
- *
- * @param object e The event object.
- * @param jQuery $el The input element.
- * @return void
- */
- onClickSubmitGutenberg: function (e, $el) {
- // validate
- var valid = acf.validateForm({
- form: $('#editor'),
- event: e,
- reset: true,
- failure: function ($form, validator) {
- var $notice = validator.get('notice').$el;
- $notice.appendTo('.components-notice-list');
- $notice.find('.acf-notice-dismiss').removeClass('small');
- }
- }); // if not valid, stop event and allow validation to continue
-
- if (!valid) {
- e.preventDefault();
- e.stopImmediatePropagation();
- }
- },
-
- /**
- * onSubmitPost
- *
- * Callback when the 'post' form is submit.
- *
- * @date 5/3/19
- * @since 5.7.13
- *
- * @param object e The event object.
- * @param jQuery $el The input element.
- * @return void
- */
- onSubmitPost: function (e, $el) {
- // Check if is preview.
- if ($('input#wp-preview').val() === 'dopreview') {
- // Ignore validation.
- this.set('ignore', true); // Unlock form to fix conflict with core "submit.edit-post" event causing all submit buttons to be disabled.
-
- acf.unlockForm($el);
- }
- },
-
- /**
- * onSubmit
- *
- * Callback when the form is submit.
- *
- * @date 4/9/18
- * @since 5.7.5
- *
- * @param object e The event object.
- * @param jQuery $el The input element.
- * @return void
- */
- onSubmit: function (e, $el) {
- // Allow form to submit if...
- if ( // Validation has been disabled.
- !this.active // Or this event is to be ignored.
- || this.get('ignore') // Or this event has already been prevented.
- || e.isDefaultPrevented()) {
- // Return early and call reset function.
- return this.allowSubmit();
- } // Validate form.
-
-
- var valid = acf.validateForm({
- form: $el,
- event: this.get('originalEvent')
- }); // If not valid, stop event to prevent form submit.
-
- if (!valid) {
- e.preventDefault();
- }
- },
-
- /**
- * allowSubmit
- *
- * Resets data during onSubmit when the form is allowed to submit.
- *
- * @date 5/3/19
- * @since 5.7.13
- *
- * @param void
- * @return void
- */
- allowSubmit: function () {
- // Reset "ignore" state.
- this.set('ignore', false); // Reset "originalEvent" object.
-
- this.set('originalEvent', false); // Return true
-
- return true;
- }
- });
- var gutenbergValidation = new acf.Model({
- wait: 'prepare',
- initialize: function () {
- // Bail early if not Gutenberg.
- if (!acf.isGutenberg()) {
- return;
- } // Custommize the editor.
-
-
- this.customizeEditor();
- },
- customizeEditor: function () {
- // Extract vars.
- var editor = wp.data.dispatch('core/editor');
- var editorSelect = wp.data.select('core/editor');
- var notices = wp.data.dispatch('core/notices'); // Backup original method.
-
- var savePost = editor.savePost; // Listen for changes to post status and perform actions:
- // a) Enable validation for "publish" action.
- // b) Remember last non "publish" status used for restoring after validation fail.
-
- var useValidation = false;
- var lastPostStatus = '';
- wp.data.subscribe(function () {
- var postStatus = editorSelect.getEditedPostAttribute('status');
- useValidation = postStatus === 'publish';
- lastPostStatus = postStatus !== 'publish' ? postStatus : lastPostStatus;
- }); // Create validation version.
-
- editor.savePost = function (options) {
- options = options || {}; // Backup vars.
-
- var _this = this;
-
- var _args = arguments; // Perform validation within a Promise.
-
- return new Promise(function (resolve, reject) {
- // Bail early if is autosave or preview.
- if (options.isAutosave || options.isPreview) {
- return resolve('Validation ignored (autosave).');
- } // Bail early if validation is not neeed.
-
-
- if (!useValidation) {
- return resolve('Validation ignored (draft).');
- } // Validate the editor form.
-
-
- var valid = acf.validateForm({
- form: $('#editor'),
- reset: true,
- complete: function ($form, validator) {
- // Always unlock the form after AJAX.
- editor.unlockPostSaving('acf');
- },
- failure: function ($form, validator) {
- // Get validation error and append to Gutenberg notices.
- var notice = validator.get('notice');
- notices.createErrorNotice(notice.get('text'), {
- id: 'acf-validation',
- isDismissible: true
- });
- notice.remove(); // Restore last non "publish" status.
-
- if (lastPostStatus) {
- editor.editPost({
- status: lastPostStatus
- });
- } // Rejext promise and prevent savePost().
-
-
- reject('Validation failed.');
- },
- success: function () {
- notices.removeNotice('acf-validation'); // Resolve promise and allow savePost().
-
- resolve('Validation success.');
- }
- }); // Resolve promise and allow savePost() if no validation is needed.
-
- if (valid) {
- resolve('Validation bypassed.'); // Otherwise, lock the form and wait for AJAX response.
- } else {
- editor.lockPostSaving('acf');
- }
- }).then(function () {
- return savePost.apply(_this, _args);
- });
- };
- }
- });
+(function($, undefined){
+
+ /**
+ * Validator
+ *
+ * The model for validating forms
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ var Validator = acf.Model.extend({
+
+ /** @var string The model identifier. */
+ id: 'Validator',
+
+ /** @var object The model data. */
+ data: {
+
+ /** @var array The form errors. */
+ errors: [],
+
+ /** @var object The form notice. */
+ notice: null,
+
+ /** @var string The form status. loading, invalid, valid */
+ status: ''
+ },
+
+ /** @var object The model events. */
+ events: {
+ 'changed:status': 'onChangeStatus'
+ },
+
+ /**
+ * addErrors
+ *
+ * Adds errors to the form.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param array errors An array of errors.
+ * @return void
+ */
+ addErrors: function( errors ){
+ errors.map( this.addError, this );
+ },
+
+ /**
+ * addError
+ *
+ * Adds and error to the form.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object error An error object containing input and message.
+ * @return void
+ */
+ addError: function( error ){
+ this.data.errors.push( error );
+ },
+
+ /**
+ * hasErrors
+ *
+ * Returns true if the form has errors.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return bool
+ */
+ hasErrors: function(){
+ return this.data.errors.length;
+ },
+
+ /**
+ * clearErrors
+ *
+ * Removes any errors.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ clearErrors: function(){
+ return this.data.errors = [];
+ },
+
+ /**
+ * getErrors
+ *
+ * Returns the forms errors.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return array
+ */
+ getErrors: function(){
+ return this.data.errors;
+ },
+
+ /**
+ * getFieldErrors
+ *
+ * Returns the forms field errors.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return array
+ */
+ getFieldErrors: function(){
+
+ // vars
+ var errors = [];
+ var inputs = [];
+
+ // loop
+ this.getErrors().map(function(error){
+
+ // bail early if global
+ if( !error.input ) return;
+
+ // update if exists
+ var i = inputs.indexOf(error.input);
+ if( i > -1 ) {
+ errors[ i ] = error;
+
+ // update
+ } else {
+ errors.push( error );
+ inputs.push( error.input );
+ }
+ });
+
+ // return
+ return errors;
+ },
+
+ /**
+ * getGlobalErrors
+ *
+ * Returns the forms global errors (errors without a specific input).
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return array
+ */
+ getGlobalErrors: function(){
+
+ // return array of errors that contain no input
+ return this.getErrors().filter(function(error){
+ return !error.input;
+ });
+ },
+
+ /**
+ * showErrors
+ *
+ * Displays all errors for this form.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ showErrors: function(){
+
+ // bail early if no errors
+ if( !this.hasErrors() ) {
+ return;
+ }
+
+ // vars
+ var fieldErrors = this.getFieldErrors();
+ var globalErrors = this.getGlobalErrors();
+
+ // vars
+ var errorCount = 0;
+ var $scrollTo = false;
+
+ // loop
+ fieldErrors.map(function( error ){
+
+ // get input
+ var $input = this.$('[name="' + error.input + '"]').first();
+
+ // if $_POST value was an array, this $input may not exist
+ if( !$input.length ) {
+ $input = this.$('[name^="' + error.input + '"]').first();
+ }
+
+ // bail early if input doesn't exist
+ if( !$input.length ) {
+ return;
+ }
+
+ // increase
+ errorCount++;
+
+ // get field
+ var field = acf.getClosestField( $input );
+
+ // show error
+ field.showError( error.message );
+
+ // set $scrollTo
+ if( !$scrollTo ) {
+ $scrollTo = field.$el;
+ }
+ }, this);
+
+ // errorMessage
+ var errorMessage = acf.__('Validation failed');
+ globalErrors.map(function( error ){
+ errorMessage += '. ' + error.message;
+ });
+ if( errorCount == 1 ) {
+ errorMessage += '. ' + acf.__('1 field requires attention');
+ } else if( errorCount > 1 ) {
+ errorMessage += '. ' + acf.__('%d fields require attention').replace('%d', errorCount);
+ }
+
+ // notice
+ if( this.has('notice') ) {
+ this.get('notice').update({
+ type: 'error',
+ text: errorMessage
+ });
+ } else {
+ var notice = acf.newNotice({
+ type: 'error',
+ text: errorMessage,
+ target: this.$el
+ });
+ this.set('notice', notice);
+ }
+
+ // if no $scrollTo, set to message
+ if( !$scrollTo ) {
+ $scrollTo = this.get('notice').$el;
+ }
+
+ // timeout
+ setTimeout(function(){
+ $("html, body").animate({ scrollTop: $scrollTo.offset().top - ( $(window).height() / 2 ) }, 500);
+ }, 10);
+ },
+
+ /**
+ * onChangeStatus
+ *
+ * Update the form class when changing the 'status' data
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object e The event object.
+ * @param jQuery $el The form element.
+ * @param string value The new status.
+ * @param string prevValue The old status.
+ * @return void
+ */
+ onChangeStatus: function( e, $el, value, prevValue ){
+ this.$el.removeClass('is-'+prevValue).addClass('is-'+value);
+ },
+
+ /**
+ * validate
+ *
+ * Vaildates the form via AJAX.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object args A list of settings to customize the validation process.
+ * @return bool True if the form is valid.
+ */
+ validate: function( args ){
+
+ // default args
+ args = acf.parseArgs(args, {
+
+ // trigger event
+ event: false,
+
+ // reset the form after submit
+ reset: false,
+
+ // loading callback
+ loading: function(){},
+
+ // complete callback
+ complete: function(){},
+
+ // failure callback
+ failure: function(){},
+
+ // success callback
+ success: function( $form ){
+ $form.submit();
+ }
+ });
+
+ // return true if is valid - allows form submit
+ if( this.get('status') == 'valid' ) {
+ return true;
+ }
+
+ // return false if is currently validating - prevents form submit
+ if( this.get('status') == 'validating' ) {
+ return false;
+ }
+
+ // return true if no ACF fields exist (no need to validate)
+ if( !this.$('.acf-field').length ) {
+ return true;
+ }
+
+ // if event is provided, create a new success callback.
+ if( args.event ) {
+ var event = $.Event(null, args.event);
+ args.success = function(){
+ acf.enableSubmit( $(event.target) ).trigger( event );
+ }
+ }
+
+ // action for 3rd party
+ acf.doAction('validation_begin', this.$el);
+
+ // lock form
+ acf.lockForm( this.$el );
+
+ // loading callback
+ args.loading( this.$el, this );
+
+ // update status
+ this.set('status', 'validating');
+
+ // success callback
+ var onSuccess = function( json ){
+
+ // validate
+ if( !acf.isAjaxSuccess(json) ) {
+ return;
+ }
+
+ // filter
+ var data = acf.applyFilters('validation_complete', json.data, this.$el, this);
+
+ // add errors
+ if( !data.valid ) {
+ this.addErrors( data.errors );
+ }
+ };
+
+ // complete
+ var onComplete = function(){
+
+ // unlock form
+ acf.unlockForm( this.$el );
+
+ // failure
+ if( this.hasErrors() ) {
+
+ // update status
+ this.set('status', 'invalid');
+
+ // action
+ acf.doAction('validation_failure', this.$el, this);
+
+ // display errors
+ this.showErrors();
+
+ // failure callback
+ args.failure( this.$el, this );
+
+ // success
+ } else {
+
+ // update status
+ this.set('status', 'valid');
+
+ // remove previous error message
+ if( this.has('notice') ) {
+ this.get('notice').update({
+ type: 'success',
+ text: acf.__('Validation successful'),
+ timeout: 1000
+ });
+ }
+
+ // action
+ acf.doAction('validation_success', this.$el, this);
+ acf.doAction('submit', this.$el);
+
+ // success callback (submit form)
+ args.success( this.$el, this );
+
+ // lock form
+ acf.lockForm( this.$el );
+
+ // reset
+ if( args.reset ) {
+ this.reset();
+ }
+ }
+
+ // complete callback
+ args.complete( this.$el, this );
+
+ // clear errors
+ this.clearErrors();
+ };
+
+ // serialize form data
+ var data = acf.serialize( this.$el );
+ data.action = 'acf/validate_save_post';
+
+ // ajax
+ $.ajax({
+ url: acf.get('ajaxurl'),
+ data: acf.prepareForAjax(data),
+ type: 'post',
+ dataType: 'json',
+ context: this,
+ success: onSuccess,
+ complete: onComplete
+ });
+
+ // return false to fail validation and allow AJAX
+ return false
+ },
+
+ /**
+ * setup
+ *
+ * Called during the constructor function to setup this instance
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $form The form element.
+ * @return void
+ */
+ setup: function( $form ){
+
+ // set $el
+ this.$el = $form;
+ },
+
+ /**
+ * reset
+ *
+ * Rests the validation to be used again.
+ *
+ * @date 6/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ reset: function(){
+
+ // reset data
+ this.set('errors', []);
+ this.set('notice', null);
+ this.set('status', '');
+
+ // unlock form
+ acf.unlockForm( this.$el );
+ }
+ });
+
+ /**
+ * getValidator
+ *
+ * Returns the instance for a given form element.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $el The form element.
+ * @return object
+ */
+ var getValidator = function( $el ){
+
+ // instantiate
+ var validator = $el.data('acf');
+ if( !validator ) {
+ validator = new Validator( $el );
+ }
+
+ // return
+ return validator;
+ };
+
+ /**
+ * acf.validateForm
+ *
+ * A helper function for the Validator.validate() function.
+ * Returns true if form is valid, or fetches a validation request and returns false.
+ *
+ * @date 4/4/18
+ * @since 5.6.9
+ *
+ * @param object args A list of settings to customize the validation process.
+ * @return bool
+ */
+
+ acf.validateForm = function( args ){
+ return getValidator( args.form ).validate( args );
+ };
+
+ /**
+ * acf.enableSubmit
+ *
+ * Enables a submit button and returns the element.
+ *
+ * @date 30/8/18
+ * @since 5.7.4
+ *
+ * @param jQuery $submit The submit button.
+ * @return jQuery
+ */
+ acf.enableSubmit = function( $submit ){
+ return $submit.removeClass('disabled');
+ };
+
+ /**
+ * acf.disableSubmit
+ *
+ * Disables a submit button and returns the element.
+ *
+ * @date 30/8/18
+ * @since 5.7.4
+ *
+ * @param jQuery $submit The submit button.
+ * @return jQuery
+ */
+ acf.disableSubmit = function( $submit ){
+ return $submit.addClass('disabled');
+ };
+
+ /**
+ * acf.showSpinner
+ *
+ * Shows the spinner element.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $spinner The spinner element.
+ * @return jQuery
+ */
+ acf.showSpinner = function( $spinner ){
+ $spinner.addClass('is-active'); // add class (WP > 4.2)
+ $spinner.css('display', 'inline-block'); // css (WP < 4.2)
+ return $spinner;
+ };
+
+ /**
+ * acf.hideSpinner
+ *
+ * Hides the spinner element.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $spinner The spinner element.
+ * @return jQuery
+ */
+ acf.hideSpinner = function( $spinner ){
+ $spinner.removeClass('is-active'); // add class (WP > 4.2)
+ $spinner.css('display', 'none'); // css (WP < 4.2)
+ return $spinner;
+ };
+
+ /**
+ * acf.lockForm
+ *
+ * Locks a form by disabeling its primary inputs and showing a spinner.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $form The form element.
+ * @return jQuery
+ */
+ acf.lockForm = function( $form ){
+
+ // vars
+ var $wrap = findSubmitWrap( $form );
+ var $submit = $wrap.find('.button, [type="submit"]');
+ var $spinner = $wrap.find('.spinner, .acf-spinner');
+
+ // hide all spinners (hides the preview spinner)
+ acf.hideSpinner( $spinner );
+
+ // lock
+ acf.disableSubmit( $submit );
+ acf.showSpinner( $spinner.last() );
+ return $form;
+ };
+
+ /**
+ * acf.unlockForm
+ *
+ * Unlocks a form by enabeling its primary inputs and hiding all spinners.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $form The form element.
+ * @return jQuery
+ */
+ acf.unlockForm = function( $form ){
+
+ // vars
+ var $wrap = findSubmitWrap( $form );
+ var $submit = $wrap.find('.button, [type="submit"]');
+ var $spinner = $wrap.find('.spinner, .acf-spinner');
+
+ // unlock
+ acf.enableSubmit( $submit );
+ acf.hideSpinner( $spinner );
+ return $form;
+ };
+
+ /**
+ * findSubmitWrap
+ *
+ * An internal function to find the 'primary' form submit wrapping element.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $form The form element.
+ * @return jQuery
+ */
+ var findSubmitWrap = function( $form ){
+
+ // default post submit div
+ var $wrap = $form.find('#submitdiv');
+ if( $wrap.length ) {
+ return $wrap;
+ }
+
+ // 3rd party publish box
+ var $wrap = $form.find('#submitpost');
+ if( $wrap.length ) {
+ return $wrap;
+ }
+
+ // term, user
+ var $wrap = $form.find('p.submit').last();
+ if( $wrap.length ) {
+ return $wrap;
+ }
+
+ // front end form
+ var $wrap = $form.find('.acf-form-submit');
+ if( $wrap.length ) {
+ return $wrap;
+ }
+
+ // default
+ return $form;
+ };
+
+ /**
+ * A debounced function to trigger a form submission.
+ *
+ * @date 15/07/2020
+ * @since 5.9.0
+ *
+ * @param type Var Description.
+ * @return type Description.
+ */
+ var submitFormDebounced = acf.debounce(function( $form ){
+ $form.submit();
+ });
+
+ /**
+ * acf.validation
+ *
+ * Global validation logic
+ *
+ * @date 4/4/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return void
+ */
+
+ acf.validation = new acf.Model({
+
+ /** @var string The model identifier. */
+ id: 'validation',
+
+ /** @var bool The active state. Set to false before 'prepare' to prevent validation. */
+ active: true,
+
+ /** @var string The model initialize time. */
+ wait: 'prepare',
+
+ /** @var object The model actions. */
+ actions: {
+ 'ready': 'addInputEvents',
+ 'append': 'addInputEvents'
+ },
+
+ /** @var object The model events. */
+ events: {
+ 'click input[type="submit"]': 'onClickSubmit',
+ 'click button[type="submit"]': 'onClickSubmit',
+ //'click #editor .editor-post-publish-button': 'onClickSubmitGutenberg',
+ 'click #save-post': 'onClickSave',
+ 'submit form#post': 'onSubmitPost',
+ 'submit form': 'onSubmit',
+ },
+
+ /**
+ * initialize
+ *
+ * Called when initializing the model.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ initialize: function(){
+
+ // check 'validation' setting
+ if( !acf.get('validation') ) {
+ this.active = false;
+ this.actions = {};
+ this.events = {};
+ }
+ },
+
+ /**
+ * enable
+ *
+ * Enables validation.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ enable: function(){
+ this.active = true;
+ },
+
+ /**
+ * disable
+ *
+ * Disables validation.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param void
+ * @return void
+ */
+ disable: function(){
+ this.active = false;
+ },
+
+ /**
+ * reset
+ *
+ * Rests the form validation to be used again
+ *
+ * @date 6/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $form The form element.
+ * @return void
+ */
+ reset: function( $form ){
+ getValidator( $form ).reset();
+ },
+
+ /**
+ * addInputEvents
+ *
+ * Adds 'invalid' event listeners to HTML inputs.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param jQuery $el The element being added / readied.
+ * @return void
+ */
+ addInputEvents: function( $el ){
+
+ // Bug exists in Safari where custom "invalid" handeling prevents draft from saving.
+ if( acf.get('browser') === 'safari' )
+ return;
+
+ // vars
+ var $inputs = $('.acf-field [name]', $el);
+
+ // check
+ if( $inputs.length ) {
+ this.on( $inputs, 'invalid', 'onInvalid' );
+ }
+ },
+
+ /**
+ * onInvalid
+ *
+ * Callback for the 'invalid' event.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object e The event object.
+ * @param jQuery $el The input element.
+ * @return void
+ */
+ onInvalid: function( e, $el ){
+
+ // prevent default
+ // - prevents browser error message
+ // - also fixes chrome bug where 'hidden-by-tab' field throws focus error
+ e.preventDefault();
+
+ // vars
+ var $form = $el.closest('form');
+
+ // check form exists
+ if( $form.length ) {
+
+ // add error to validator
+ getValidator( $form ).addError({
+ input: $el.attr('name'),
+ message: acf.strEscape( e.target.validationMessage )
+ });
+
+ // trigger submit on $form
+ // - allows for "save", "preview" and "publish" to work
+ submitFormDebounced( $form );
+ }
+ },
+
+ /**
+ * onClickSubmit
+ *
+ * Callback when clicking submit.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object e The event object.
+ * @param jQuery $el The input element.
+ * @return void
+ */
+ onClickSubmit: function( e, $el ){
+
+ // store the "click event" for later use in this.onSubmit()
+ this.set('originalEvent', e);
+ },
+
+ /**
+ * onClickSave
+ *
+ * Set ignore to true when saving a draft.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object e The event object.
+ * @param jQuery $el The input element.
+ * @return void
+ */
+ onClickSave: function( e, $el ) {
+ this.set('ignore', true);
+ },
+
+ /**
+ * onClickSubmitGutenberg
+ *
+ * Custom validation event for the gutenberg editor.
+ *
+ * @date 29/10/18
+ * @since 5.8.0
+ *
+ * @param object e The event object.
+ * @param jQuery $el The input element.
+ * @return void
+ */
+ onClickSubmitGutenberg: function( e, $el ){
+
+ // validate
+ var valid = acf.validateForm({
+ form: $('#editor'),
+ event: e,
+ reset: true,
+ failure: function( $form, validator ){
+ var $notice = validator.get('notice').$el;
+ $notice.appendTo('.components-notice-list');
+ $notice.find('.acf-notice-dismiss').removeClass('small');
+ }
+ });
+
+ // if not valid, stop event and allow validation to continue
+ if( !valid ) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ }
+ },
+
+ /**
+ * onSubmitPost
+ *
+ * Callback when the 'post' form is submit.
+ *
+ * @date 5/3/19
+ * @since 5.7.13
+ *
+ * @param object e The event object.
+ * @param jQuery $el The input element.
+ * @return void
+ */
+ onSubmitPost: function( e, $el ) {
+
+ // Check if is preview.
+ if( $('input#wp-preview').val() === 'dopreview' ) {
+
+ // Ignore validation.
+ this.set('ignore', true);
+
+ // Unlock form to fix conflict with core "submit.edit-post" event causing all submit buttons to be disabled.
+ acf.unlockForm( $el )
+ }
+ },
+
+ /**
+ * onSubmit
+ *
+ * Callback when the form is submit.
+ *
+ * @date 4/9/18
+ * @since 5.7.5
+ *
+ * @param object e The event object.
+ * @param jQuery $el The input element.
+ * @return void
+ */
+ onSubmit: function( e, $el ){
+
+ // Allow form to submit if...
+ if(
+ // Validation has been disabled.
+ !this.active
+
+ // Or this event is to be ignored.
+ || this.get('ignore')
+
+ // Or this event has already been prevented.
+ || e.isDefaultPrevented()
+ ) {
+ // Return early and call reset function.
+ return this.allowSubmit();
+ }
+
+ // Validate form.
+ var valid = acf.validateForm({
+ form: $el,
+ event: this.get('originalEvent')
+ });
+
+ // If not valid, stop event to prevent form submit.
+ if( !valid ) {
+ e.preventDefault();
+ }
+ },
+
+ /**
+ * allowSubmit
+ *
+ * Resets data during onSubmit when the form is allowed to submit.
+ *
+ * @date 5/3/19
+ * @since 5.7.13
+ *
+ * @param void
+ * @return void
+ */
+ allowSubmit: function(){
+
+ // Reset "ignore" state.
+ this.set('ignore', false);
+
+ // Reset "originalEvent" object.
+ this.set('originalEvent', false);
+
+ // Return true
+ return true;
+ }
+ });
+
+ var gutenbergValidation = new acf.Model({
+ wait: 'prepare',
+ initialize: function(){
+
+ // Bail early if not Gutenberg.
+ if( !acf.isGutenberg() ) {
+ return;
+ }
+
+ // Custommize the editor.
+ this.customizeEditor();
+ },
+ customizeEditor: function(){
+
+ // Extract vars.
+ var editor = wp.data.dispatch( 'core/editor' );
+ var editorSelect = wp.data.select( 'core/editor' );
+ var notices = wp.data.dispatch( 'core/notices' );
+
+ // Backup original method.
+ var savePost = editor.savePost;
+
+ // Listen for changes to post status and perform actions:
+ // a) Enable validation for "publish" action.
+ // b) Remember last non "publish" status used for restoring after validation fail.
+ var useValidation = false;
+ var lastPostStatus = '';
+ wp.data.subscribe(function() {
+ var postStatus = editorSelect.getEditedPostAttribute( 'status' );
+ useValidation = ( postStatus === 'publish' );
+ lastPostStatus = ( postStatus !== 'publish' ) ? postStatus : lastPostStatus;
+ });
+
+ // Create validation version.
+ editor.savePost = function( options ){
+ options = options || {};
+
+ // Backup vars.
+ var _this = this;
+ var _args = arguments;
+
+ // Perform validation within a Promise.
+ return new Promise(function( resolve, reject ) {
+
+ // Bail early if is autosave or preview.
+ if( options.isAutosave || options.isPreview ) {
+ return resolve( 'Validation ignored (autosave).' );
+ }
+
+ // Bail early if validation is not neeed.
+ if( !useValidation ) {
+ return resolve( 'Validation ignored (draft).' );
+ }
+
+ // Validate the editor form.
+ var valid = acf.validateForm({
+ form: $('#editor'),
+ reset: true,
+ complete: function( $form, validator ){
+
+ // Always unlock the form after AJAX.
+ editor.unlockPostSaving( 'acf' );
+ },
+ failure: function( $form, validator ){
+
+ // Get validation error and append to Gutenberg notices.
+ var notice = validator.get('notice');
+ notices.createErrorNotice( notice.get('text'), {
+ id: 'acf-validation',
+ isDismissible: true
+ });
+ notice.remove();
+
+ // Restore last non "publish" status.
+ if( lastPostStatus ) {
+ editor.editPost({
+ status: lastPostStatus
+ });
+ }
+
+ // Rejext promise and prevent savePost().
+ reject( 'Validation failed.' );
+ },
+ success: function(){
+ notices.removeNotice( 'acf-validation' );
+
+ // Resolve promise and allow savePost().
+ resolve( 'Validation success.' );
+ }
+ });
+
+ // Resolve promise and allow savePost() if no validation is needed.
+ if( valid ) {
+ resolve( 'Validation bypassed.' );
+
+ // Otherwise, lock the form and wait for AJAX response.
+ } else {
+ editor.lockPostSaving( 'acf' );
+ }
+ }).then(function(){
+ return savePost.apply(_this, _args);
+ });
+ };
+ }
+ });
+
})(jQuery);
+(function($, undefined){
+
+ /**
+ * refreshHelper
+ *
+ * description
+ *
+ * @date 1/7/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var refreshHelper = new acf.Model({
+ priority: 90,
+ actions: {
+ 'new_field': 'refresh',
+ 'show_field': 'refresh',
+ 'hide_field': 'refresh',
+ 'remove_field': 'refresh',
+ 'unmount_field': 'refresh',
+ 'remount_field': 'refresh',
+ },
+ refresh: function(){
+ acf.refresh();
+ }
+ });
+
+ /**
+ * mountHelper
+ *
+ * Adds compatiblity for the 'unmount' and 'remount' actions added in 5.8.0
+ *
+ * @date 7/3/19
+ * @since 5.7.14
+ *
+ * @param void
+ * @return void
+ */
+ var mountHelper = new acf.Model({
+ priority: 1,
+ actions: {
+ 'sortstart': 'onSortstart',
+ 'sortstop': 'onSortstop'
+ },
+ onSortstart: function( $item ){
+ acf.doAction('unmount', $item);
+ },
+ onSortstop: function( $item ){
+ acf.doAction('remount', $item);
+ }
+ });
+
+ /**
+ * sortableHelper
+ *
+ * Adds compatibility for sorting a
element
+ *
+ * @date 6/3/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return void
+ */
+
+ var sortableHelper = new acf.Model({
+ actions: {
+ 'sortstart': 'onSortstart'
+ },
+ onSortstart: function( $item, $placeholder ){
+
+ // if $item is a tr, apply some css to the elements
+ if( $item.is('tr') ) {
+
+ // replace $placeholder children with a single td
+ // fixes "width calculation issues" due to conditional logic hiding some children
+ $placeholder.html(' ');
+
+ // add helper class to remove absolute positioning
+ $item.addClass('acf-sortable-tr-helper');
+
+ // set fixed widths for children
+ $item.children().each(function(){
+ $(this).width( $(this).width() );
+ });
+
+ // mimic height
+ $placeholder.height( $item.height() + 'px' );
+
+ // remove class
+ $item.removeClass('acf-sortable-tr-helper');
+ }
+ }
+ });
+
+ /**
+ * duplicateHelper
+ *
+ * Fixes browser bugs when duplicating an element
+ *
+ * @date 6/3/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return void
+ */
+
+ var duplicateHelper = new acf.Model({
+ actions: {
+ 'after_duplicate': 'onAfterDuplicate'
+ },
+ onAfterDuplicate: function( $el, $el2 ){
+
+ // get original values
+ var vals = [];
+ $el.find('select').each(function(i){
+ vals.push( $(this).val() );
+ });
+
+ // set duplicate values
+ $el2.find('select').each(function(i){
+ $(this).val( vals[i] );
+ });
+ }
+ });
+
+ /**
+ * tableHelper
+ *
+ * description
+ *
+ * @date 6/3/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var tableHelper = new acf.Model({
+
+ id: 'tableHelper',
+
+ priority: 20,
+
+ actions: {
+ 'refresh': 'renderTables'
+ },
+
+ renderTables: function( $el ){
+
+ // loop
+ var self = this;
+ $('.acf-table:visible').each(function(){
+ self.renderTable( $(this) );
+ });
+ },
+
+ renderTable: function( $table ){
+
+ // vars
+ var $ths = $table.find('> thead > tr:visible > th[data-key]');
+ var $tds = $table.find('> tbody > tr:visible > td[data-key]');
+
+ // bail early if no thead
+ if( !$ths.length || !$tds.length ) {
+ return false;
+ }
+
+
+ // visiblity
+ $ths.each(function( i ){
+
+ // vars
+ var $th = $(this);
+ var key = $th.data('key');
+ var $cells = $tds.filter('[data-key="' + key + '"]');
+ var $hidden = $cells.filter('.acf-hidden');
+
+ // always remove empty and allow cells to be hidden
+ $cells.removeClass('acf-empty');
+
+ // hide $th if all cells are hidden
+ if( $cells.length === $hidden.length ) {
+ acf.hide( $th );
+
+ // force all hidden cells to appear empty
+ } else {
+ acf.show( $th );
+ $hidden.addClass('acf-empty');
+ }
+ });
+
+
+ // clear width
+ $ths.css('width', 'auto');
+
+ // get visible
+ $ths = $ths.not('.acf-hidden');
+
+ // vars
+ var availableWidth = 100;
+ var colspan = $ths.length;
+
+ // set custom widths first
+ var $fixedWidths = $ths.filter('[data-width]');
+ $fixedWidths.each(function(){
+ var width = $(this).data('width');
+ $(this).css('width', width + '%');
+ availableWidth -= width;
+ });
+
+ // set auto widths
+ var $auoWidths = $ths.not('[data-width]');
+ if( $auoWidths.length ) {
+ var width = availableWidth / $auoWidths.length;
+ $auoWidths.css('width', width + '%');
+ availableWidth = 0;
+ }
+
+ // avoid stretching issue
+ if( availableWidth > 0 ) {
+ $ths.last().css('width', 'auto');
+ }
+
+
+ // update colspan on collapsed
+ $tds.filter('.-collapsed-target').each(function(){
+
+ // vars
+ var $td = $(this);
+
+ // check if collapsed
+ if( $td.parent().hasClass('-collapsed') ) {
+ $td.attr('colspan', $ths.length);
+ } else {
+ $td.removeAttr('colspan');
+ }
+ });
+ }
+ });
+
+
+ /**
+ * fieldsHelper
+ *
+ * description
+ *
+ * @date 6/3/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var fieldsHelper = new acf.Model({
+
+ id: 'fieldsHelper',
+
+ priority: 30,
+
+ actions: {
+ 'refresh': 'renderGroups'
+ },
+
+ renderGroups: function(){
+
+ // loop
+ var self = this;
+ $('.acf-fields:visible').each(function(){
+ self.renderGroup( $(this) );
+ });
+ },
+
+ renderGroup: function( $el ){
+
+ // vars
+ var top = 0;
+ var height = 0;
+ var $row = $();
+
+ // get fields
+ var $fields = $el.children('.acf-field[data-width]:visible');
+
+ // bail early if no fields
+ if( !$fields.length ) {
+ return false;
+ }
+
+ // bail ealry if is .-left
+ if( $el.hasClass('-left') ) {
+ $fields.removeAttr('data-width');
+ $fields.css('width', 'auto');
+ return false;
+ }
+
+ // reset fields
+ $fields.removeClass('-r0 -c0').css({'min-height': 0});
+
+ // loop
+ $fields.each(function( i ){
+
+ // vars
+ var $field = $(this);
+ var position = $field.position();
+ var thisTop = Math.ceil( position.top );
+ var thisLeft = Math.ceil( position.left );
+
+ // detect change in row
+ if( $row.length && thisTop > top ) {
-(function ($, undefined) {
- /**
- * refreshHelper
- *
- * description
- *
- * @date 1/7/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
- var refreshHelper = new acf.Model({
- priority: 90,
- actions: {
- 'new_field': 'refresh',
- 'show_field': 'refresh',
- 'hide_field': 'refresh',
- 'remove_field': 'refresh',
- 'unmount_field': 'refresh',
- 'remount_field': 'refresh'
- },
- refresh: function () {
- acf.refresh();
- }
- });
- /**
- * mountHelper
- *
- * Adds compatiblity for the 'unmount' and 'remount' actions added in 5.8.0
- *
- * @date 7/3/19
- * @since 5.7.14
- *
- * @param void
- * @return void
- */
+ // set previous heights
+ $row.css({'min-height': height+'px'});
+
+ // update position due to change in row above
+ position = $field.position();
+ thisTop = Math.ceil( position.top );
+ thisLeft = Math.ceil( position.left );
+
+ // reset vars
+ top = 0;
+ height = 0;
+ $row = $();
+ }
+
+ // rtl
+ if( acf.get('rtl') ) {
+ thisLeft = Math.ceil( $field.parent().width() - (position.left + $field.outerWidth()) );
+ }
+
+ // add classes
+ if( thisTop == 0 ) {
+ $field.addClass('-r0');
+ } else if( thisLeft == 0 ) {
+ $field.addClass('-c0');
+ }
+
+ // get height after class change
+ // - add 1 for subpixel rendering
+ var thisHeight = Math.ceil( $field.outerHeight() ) + 1;
+
+ // set height
+ height = Math.max( height, thisHeight );
+
+ // set y
+ top = Math.max( top, thisTop );
+
+ // append
+ $row = $row.add( $field );
+ });
+
+ // clean up
+ if( $row.length ) {
+ $row.css({'min-height': height+'px'});
+ }
+ }
+ });
- var mountHelper = new acf.Model({
- priority: 1,
- actions: {
- 'sortstart': 'onSortstart',
- 'sortstop': 'onSortstop'
- },
- onSortstart: function ($item) {
- acf.doAction('unmount', $item);
- },
- onSortstop: function ($item) {
- acf.doAction('remount', $item);
- }
- });
- /**
- * sortableHelper
- *
- * Adds compatibility for sorting a element
- *
- * @date 6/3/18
- * @since 5.6.9
- *
- * @param void
- * @return void
- */
-
- var sortableHelper = new acf.Model({
- actions: {
- 'sortstart': 'onSortstart'
- },
- onSortstart: function ($item, $placeholder) {
- // if $item is a tr, apply some css to the elements
- if ($item.is('tr')) {
- // replace $placeholder children with a single td
- // fixes "width calculation issues" due to conditional logic hiding some children
- $placeholder.html(' '); // add helper class to remove absolute positioning
-
- $item.addClass('acf-sortable-tr-helper'); // set fixed widths for children
-
- $item.children().each(function () {
- $(this).width($(this).width());
- }); // mimic height
-
- $placeholder.height($item.height() + 'px'); // remove class
-
- $item.removeClass('acf-sortable-tr-helper');
- }
- }
- });
- /**
- * duplicateHelper
- *
- * Fixes browser bugs when duplicating an element
- *
- * @date 6/3/18
- * @since 5.6.9
- *
- * @param void
- * @return void
- */
-
- var duplicateHelper = new acf.Model({
- actions: {
- 'after_duplicate': 'onAfterDuplicate'
- },
- onAfterDuplicate: function ($el, $el2) {
- // get original values
- var vals = [];
- $el.find('select').each(function (i) {
- vals.push($(this).val());
- }); // set duplicate values
-
- $el2.find('select').each(function (i) {
- $(this).val(vals[i]);
- });
- }
- });
- /**
- * tableHelper
- *
- * description
- *
- * @date 6/3/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var tableHelper = new acf.Model({
- id: 'tableHelper',
- priority: 20,
- actions: {
- 'refresh': 'renderTables'
- },
- renderTables: function ($el) {
- // loop
- var self = this;
- $('.acf-table:visible').each(function () {
- self.renderTable($(this));
- });
- },
- renderTable: function ($table) {
- // vars
- var $ths = $table.find('> thead > tr:visible > th[data-key]');
- var $tds = $table.find('> tbody > tr:visible > td[data-key]'); // bail early if no thead
-
- if (!$ths.length || !$tds.length) {
- return false;
- } // visiblity
-
-
- $ths.each(function (i) {
- // vars
- var $th = $(this);
- var key = $th.data('key');
- var $cells = $tds.filter('[data-key="' + key + '"]');
- var $hidden = $cells.filter('.acf-hidden'); // always remove empty and allow cells to be hidden
-
- $cells.removeClass('acf-empty'); // hide $th if all cells are hidden
-
- if ($cells.length === $hidden.length) {
- acf.hide($th); // force all hidden cells to appear empty
- } else {
- acf.show($th);
- $hidden.addClass('acf-empty');
- }
- }); // clear width
-
- $ths.css('width', 'auto'); // get visible
-
- $ths = $ths.not('.acf-hidden'); // vars
-
- var availableWidth = 100;
- var colspan = $ths.length; // set custom widths first
-
- var $fixedWidths = $ths.filter('[data-width]');
- $fixedWidths.each(function () {
- var width = $(this).data('width');
- $(this).css('width', width + '%');
- availableWidth -= width;
- }); // set auto widths
-
- var $auoWidths = $ths.not('[data-width]');
-
- if ($auoWidths.length) {
- var width = availableWidth / $auoWidths.length;
- $auoWidths.css('width', width + '%');
- availableWidth = 0;
- } // avoid stretching issue
-
-
- if (availableWidth > 0) {
- $ths.last().css('width', 'auto');
- } // update colspan on collapsed
-
-
- $tds.filter('.-collapsed-target').each(function () {
- // vars
- var $td = $(this); // check if collapsed
-
- if ($td.parent().hasClass('-collapsed')) {
- $td.attr('colspan', $ths.length);
- } else {
- $td.removeAttr('colspan');
- }
- });
- }
- });
- /**
- * fieldsHelper
- *
- * description
- *
- * @date 6/3/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var fieldsHelper = new acf.Model({
- id: 'fieldsHelper',
- priority: 30,
- actions: {
- 'refresh': 'renderGroups'
- },
- renderGroups: function () {
- // loop
- var self = this;
- $('.acf-fields:visible').each(function () {
- self.renderGroup($(this));
- });
- },
- renderGroup: function ($el) {
- // vars
- var top = 0;
- var height = 0;
- var $row = $(); // get fields
-
- var $fields = $el.children('.acf-field[data-width]:visible'); // bail early if no fields
-
- if (!$fields.length) {
- return false;
- } // bail ealry if is .-left
-
-
- if ($el.hasClass('-left')) {
- $fields.removeAttr('data-width');
- $fields.css('width', 'auto');
- return false;
- } // reset fields
-
-
- $fields.removeClass('-r0 -c0').css({
- 'min-height': 0
- }); // loop
-
- $fields.each(function (i) {
- // vars
- var $field = $(this);
- var position = $field.position();
- var thisTop = Math.ceil(position.top);
- var thisLeft = Math.ceil(position.left); // detect change in row
-
- if ($row.length && thisTop > top) {
- // set previous heights
- $row.css({
- 'min-height': height + 'px'
- }); // update position due to change in row above
-
- position = $field.position();
- thisTop = Math.ceil(position.top);
- thisLeft = Math.ceil(position.left); // reset vars
-
- top = 0;
- height = 0;
- $row = $();
- } // rtl
-
-
- if (acf.get('rtl')) {
- thisLeft = Math.ceil($field.parent().width() - (position.left + $field.outerWidth()));
- } // add classes
-
-
- if (thisTop == 0) {
- $field.addClass('-r0');
- } else if (thisLeft == 0) {
- $field.addClass('-c0');
- } // get height after class change
- // - add 1 for subpixel rendering
-
-
- var thisHeight = Math.ceil($field.outerHeight()) + 1; // set height
-
- height = Math.max(height, thisHeight); // set y
-
- top = Math.max(top, thisTop); // append
-
- $row = $row.add($field);
- }); // clean up
-
- if ($row.length) {
- $row.css({
- 'min-height': height + 'px'
- });
- }
- }
- });
- /**
- * Adds a body class when holding down the "shift" key.
- *
- * @date 06/05/2020
- * @since 5.9.0
- */
-
- var bodyClassShiftHelper = new acf.Model({
- id: 'bodyClassShiftHelper',
- events: {
- 'keydown': 'onKeyDown',
- 'keyup': 'onKeyUp'
- },
- isShiftKey: function (e) {
- return e.keyCode === 16;
- },
- onKeyDown: function (e) {
- if (this.isShiftKey(e)) {
- $('body').addClass('acf-keydown-shift');
- }
- },
- onKeyUp: function (e) {
- if (this.isShiftKey(e)) {
- $('body').removeClass('acf-keydown-shift');
- }
- }
- });
+ /**
+ * Adds a body class when holding down the "shift" key.
+ *
+ * @date 06/05/2020
+ * @since 5.9.0
+ */
+ var bodyClassShiftHelper = new acf.Model({
+ id: 'bodyClassShiftHelper',
+ events: {
+ 'keydown': 'onKeyDown',
+ 'keyup': 'onKeyUp'
+ },
+ isShiftKey: function( e ){
+ return ( e.keyCode === 16 );
+ },
+ onKeyDown: function( e ){
+ if( this.isShiftKey(e) ) {
+ $('body').addClass('acf-keydown-shift');
+ }
+ },
+ onKeyUp: function( e ){
+ if( this.isShiftKey(e) ) {
+ $('body').removeClass('acf-keydown-shift');
+ }
+ },
+ });
+
})(jQuery);
-
-(function ($, undefined) {
- /**
- * acf.newCompatibility
- *
- * Inserts a new __proto__ object compatibility layer
- *
- * @date 15/2/18
- * @since 5.6.9
- *
- * @param object instance The object to modify.
- * @param object compatibilty Optional. The compatibilty layer.
- * @return object compatibilty
- */
- acf.newCompatibility = function (instance, compatibilty) {
- // defaults
- compatibilty = compatibilty || {}; // inherit __proto_-
-
- compatibilty.__proto__ = instance.__proto__; // inject
-
- instance.__proto__ = compatibilty; // reference
-
- instance.compatibility = compatibilty; // return
-
- return compatibilty;
- };
- /**
- * acf.getCompatibility
- *
- * Returns the compatibility layer for a given instance
- *
- * @date 13/3/18
- * @since 5.6.9
- *
- * @param object instance The object to look in.
- * @return object|null compatibility The compatibility object or null on failure.
- */
-
-
- acf.getCompatibility = function (instance) {
- return instance.compatibility || null;
- };
- /**
- * acf (compatibility)
- *
- * Compatibility layer for the acf object
- *
- * @date 15/2/18
- * @since 5.6.9
- *
- * @param void
- * @return void
- */
-
-
- var _acf = acf.newCompatibility(acf, {
- // storage
- l10n: {},
- o: {},
- fields: {},
- // changed function names
- update: acf.set,
- add_action: acf.addAction,
- remove_action: acf.removeAction,
- do_action: acf.doAction,
- add_filter: acf.addFilter,
- remove_filter: acf.removeFilter,
- apply_filters: acf.applyFilters,
- parse_args: acf.parseArgs,
- disable_el: acf.disable,
- disable_form: acf.disable,
- enable_el: acf.enable,
- enable_form: acf.enable,
- update_user_setting: acf.updateUserSetting,
- prepare_for_ajax: acf.prepareForAjax,
- is_ajax_success: acf.isAjaxSuccess,
- remove_el: acf.remove,
- remove_tr: acf.remove,
- str_replace: acf.strReplace,
- render_select: acf.renderSelect,
- get_uniqid: acf.uniqid,
- serialize_form: acf.serialize,
- esc_html: acf.strEscape,
- str_sanitize: acf.strSanitize
- });
-
- _acf._e = function (k1, k2) {
- // defaults
- k1 = k1 || '';
- k2 = k2 || ''; // compability
-
- var compatKey = k2 ? k1 + '.' + k2 : k1;
- var compats = {
- 'image.select': 'Select Image',
- 'image.edit': 'Edit Image',
- 'image.update': 'Update Image'
- };
-
- if (compats[compatKey]) {
- return acf.__(compats[compatKey]);
- } // try k1
-
-
- var string = this.l10n[k1] || ''; // try k2
-
- if (k2) {
- string = string[k2] || '';
- } // return
-
-
- return string;
- };
-
- _acf.get_selector = function (s) {
- // vars
- var selector = '.acf-field'; // bail early if no search
-
- if (!s) {
- return selector;
- } // compatibility with object
-
-
- if ($.isPlainObject(s)) {
- if ($.isEmptyObject(s)) {
- return selector;
- } else {
- for (var k in s) {
- s = s[k];
- break;
- }
- }
- } // append
-
-
- selector += '-' + s; // replace underscores (split/join replaces all and is faster than regex!)
-
- selector = acf.strReplace('_', '-', selector); // remove potential double up
-
- selector = acf.strReplace('field-field-', 'field-', selector); // return
-
- return selector;
- };
-
- _acf.get_fields = function (s, $el, all) {
- // args
- var args = {
- is: s || '',
- parent: $el || false,
- suppressFilters: all || false
- }; // change 'field_123' to '.acf-field-123'
-
- if (args.is) {
- args.is = this.get_selector(args.is);
- } // return
-
-
- return acf.findFields(args);
- };
-
- _acf.get_field = function (s, $el) {
- // get fields
- var $fields = this.get_fields.apply(this, arguments); // return
-
- if ($fields.length) {
- return $fields.first();
- } else {
- return false;
- }
- };
-
- _acf.get_closest_field = function ($el, s) {
- return $el.closest(this.get_selector(s));
- };
-
- _acf.get_field_wrap = function ($el) {
- return $el.closest(this.get_selector());
- };
-
- _acf.get_field_key = function ($field) {
- return $field.data('key');
- };
-
- _acf.get_field_type = function ($field) {
- return $field.data('type');
- };
-
- _acf.get_data = function ($el, defaults) {
- return acf.parseArgs($el.data(), defaults);
- };
-
- _acf.maybe_get = function (obj, key, value) {
- // default
- if (value === undefined) {
- value = null;
- } // get keys
-
-
- keys = String(key).split('.'); // acf.isget
-
- for (var i = 0; i < keys.length; i++) {
- if (!obj.hasOwnProperty(keys[i])) {
- return value;
- }
-
- obj = obj[keys[i]];
- }
-
- return obj;
- };
- /**
- * hooks
- *
- * Modify add_action and add_filter functions to add compatibility with changed $field parameter
- * Using the acf.add_action() or acf.add_filter() functions will interpret new field parameters as jQuery $field
- *
- * @date 12/5/18
- * @since 5.6.9
- *
- * @param void
- * @return void
- */
-
-
- var compatibleArgument = function (arg) {
- return arg instanceof acf.Field ? arg.$el : arg;
- };
-
- var compatibleArguments = function (args) {
- return acf.arrayArgs(args).map(compatibleArgument);
- };
-
- var compatibleCallback = function (origCallback) {
- return function () {
- // convert to compatible arguments
- if (arguments.length) {
- var args = compatibleArguments(arguments); // add default argument for 'ready', 'append' and 'load' events
- } else {
- var args = [$(document)];
- } // return
-
-
- return origCallback.apply(this, args);
- };
- };
-
- _acf.add_action = function (action, callback, priority, context) {
- // handle multiple actions
- var actions = action.split(' ');
- var length = actions.length;
-
- if (length > 1) {
- for (var i = 0; i < length; i++) {
- action = actions[i];
-
- _acf.add_action.apply(this, arguments);
- }
-
- return this;
- } // single
-
-
- var callback = compatibleCallback(callback);
- return acf.addAction.apply(this, arguments);
- };
-
- _acf.add_filter = function (action, callback, priority, context) {
- var callback = compatibleCallback(callback);
- return acf.addFilter.apply(this, arguments);
- };
- /*
- * acf.model
- *
- * This model acts as a scafold for action.event driven modules
- *
- * @type object
- * @date 8/09/2014
- * @since 5.0.0
- *
- * @param (object)
- * @return (object)
- */
-
-
- _acf.model = {
- actions: {},
- filters: {},
- events: {},
- extend: function (args) {
- // extend
- var model = $.extend({}, this, args); // setup actions
-
- $.each(model.actions, function (name, callback) {
- model._add_action(name, callback);
- }); // setup filters
-
- $.each(model.filters, function (name, callback) {
- model._add_filter(name, callback);
- }); // setup events
-
- $.each(model.events, function (name, callback) {
- model._add_event(name, callback);
- }); // return
-
- return model;
- },
- _add_action: function (name, callback) {
- // split
- var model = this,
- data = name.split(' '); // add missing priority
-
- var name = data[0] || '',
- priority = data[1] || 10; // add action
-
- acf.add_action(name, model[callback], priority, model);
- },
- _add_filter: function (name, callback) {
- // split
- var model = this,
- data = name.split(' '); // add missing priority
-
- var name = data[0] || '',
- priority = data[1] || 10; // add action
-
- acf.add_filter(name, model[callback], priority, model);
- },
- _add_event: function (name, callback) {
- // vars
- var model = this,
- i = name.indexOf(' '),
- event = i > 0 ? name.substr(0, i) : name,
- selector = i > 0 ? name.substr(i + 1) : ''; // event
-
- var fn = function (e) {
- // append $el to event object
- e.$el = $(this); // append $field to event object (used in field group)
-
- if (acf.field_group) {
- e.$field = e.$el.closest('.acf-field-object');
- } // event
-
-
- if (typeof model.event === 'function') {
- e = model.event(e);
- } // callback
-
-
- model[callback].apply(model, arguments);
- }; // add event
-
-
- if (selector) {
- $(document).on(event, selector, fn);
- } else {
- $(document).on(event, fn);
- }
- },
- get: function (name, value) {
- // defaults
- value = value || null; // get
-
- if (typeof this[name] !== 'undefined') {
- value = this[name];
- } // return
-
-
- return value;
- },
- set: function (name, value) {
- // set
- this[name] = value; // function for 3rd party
-
- if (typeof this['_set_' + name] === 'function') {
- this['_set_' + name].apply(this);
- } // return for chaining
-
-
- return this;
- }
- };
- /*
- * field
- *
- * This model sets up many of the field's interactions
- *
- * @type function
- * @date 21/02/2014
- * @since 3.5.1
- *
- * @param n/a
- * @return n/a
- */
-
- _acf.field = acf.model.extend({
- type: '',
- o: {},
- $field: null,
- _add_action: function (name, callback) {
- // vars
- var model = this; // update name
-
- name = name + '_field/type=' + model.type; // add action
-
- acf.add_action(name, function ($field) {
- // focus
- model.set('$field', $field); // callback
-
- model[callback].apply(model, arguments);
- });
- },
- _add_filter: function (name, callback) {
- // vars
- var model = this; // update name
-
- name = name + '_field/type=' + model.type; // add action
-
- acf.add_filter(name, function ($field) {
- // focus
- model.set('$field', $field); // callback
-
- model[callback].apply(model, arguments);
- });
- },
- _add_event: function (name, callback) {
- // vars
- var model = this,
- event = name.substr(0, name.indexOf(' ')),
- selector = name.substr(name.indexOf(' ') + 1),
- context = acf.get_selector(model.type); // add event
-
- $(document).on(event, context + ' ' + selector, function (e) {
- // vars
- var $el = $(this);
- var $field = acf.get_closest_field($el, model.type); // bail early if no field
-
- if (!$field.length) return; // focus
-
- if (!$field.is(model.$field)) {
- model.set('$field', $field);
- } // append to event
-
-
- e.$el = $el;
- e.$field = $field; // callback
-
- model[callback].apply(model, [e]);
- });
- },
- _set_$field: function () {
- // callback
- if (typeof this.focus === 'function') {
- this.focus();
- }
- },
- // depreciated
- doFocus: function ($field) {
- return this.set('$field', $field);
- }
- });
- /**
- * validation
- *
- * description
- *
- * @date 15/2/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- var _validation = acf.newCompatibility(acf.validation, {
- remove_error: function ($field) {
- acf.getField($field).removeError();
- },
- add_warning: function ($field, message) {
- acf.getField($field).showNotice({
- text: message,
- type: 'warning',
- timeout: 1000
- });
- },
- fetch: acf.validateForm,
- enableSubmit: acf.enableSubmit,
- disableSubmit: acf.disableSubmit,
- showSpinner: acf.showSpinner,
- hideSpinner: acf.hideSpinner,
- unlockForm: acf.unlockForm,
- lockForm: acf.lockForm
- });
- /**
- * tooltip
- *
- * description
- *
- * @date 15/2/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
-
- _acf.tooltip = {
- tooltip: function (text, $el) {
- var tooltip = acf.newTooltip({
- text: text,
- target: $el
- }); // return
-
- return tooltip.$el;
- },
- temp: function (text, $el) {
- var tooltip = acf.newTooltip({
- text: text,
- target: $el,
- timeout: 250
- });
- },
- confirm: function ($el, callback, text, button_y, button_n) {
- var tooltip = acf.newTooltip({
- confirm: true,
- text: text,
- target: $el,
- confirm: function () {
- callback(true);
- },
- cancel: function () {
- callback(false);
- }
- });
- },
- confirm_remove: function ($el, callback) {
- var tooltip = acf.newTooltip({
- confirmRemove: true,
- target: $el,
- confirm: function () {
- callback(true);
- },
- cancel: function () {
- callback(false);
- }
- });
- }
- };
- /**
- * tooltip
- *
- * description
- *
- * @date 15/2/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- _acf.media = new acf.Model({
- activeFrame: false,
- actions: {
- 'new_media_popup': 'onNewMediaPopup'
- },
- frame: function () {
- return this.activeFrame;
- },
- onNewMediaPopup: function (popup) {
- this.activeFrame = popup.frame;
- },
- popup: function (props) {
- // update props
- if (props.mime_types) {
- props.allowedTypes = props.mime_types;
- }
-
- if (props.id) {
- props.attachment = props.id;
- } // new
-
-
- var popup = acf.newMediaPopup(props); // append
-
- /*
- if( props.selected ) {
- popup.selected = props.selected;
- }
- */
- // return
-
- return popup.frame;
- }
- });
- /**
- * Select2
- *
- * description
- *
- * @date 11/6/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- _acf.select2 = {
- init: function ($select, args, $field) {
- // compatible args
- if (args.allow_null) {
- args.allowNull = args.allow_null;
- }
-
- if (args.ajax_action) {
- args.ajaxAction = args.ajax_action;
- }
-
- if ($field) {
- args.field = acf.getField($field);
- } // return
-
-
- return acf.newSelect2($select, args);
- },
- destroy: function ($select) {
- return acf.getInstance($select).destroy();
- }
- };
- /**
- * postbox
- *
- * description
- *
- * @date 11/6/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- _acf.postbox = {
- render: function (args) {
- // compatible args
- if (args.edit_url) {
- args.editLink = args.edit_url;
- }
-
- if (args.edit_title) {
- args.editTitle = args.edit_title;
- } // return
-
-
- return acf.newPostbox(args);
- }
- };
- /**
- * acf.screen
- *
- * description
- *
- * @date 11/6/18
- * @since 5.6.9
- *
- * @param type $var Description. Default.
- * @return type Description.
- */
-
- acf.newCompatibility(acf.screen, {
- update: function () {
- return this.set.apply(this, arguments);
- },
- fetch: acf.screen.check
- });
- _acf.ajax = acf.screen;
+(function($, undefined){
+
+ /**
+ * acf.newCompatibility
+ *
+ * Inserts a new __proto__ object compatibility layer
+ *
+ * @date 15/2/18
+ * @since 5.6.9
+ *
+ * @param object instance The object to modify.
+ * @param object compatibilty Optional. The compatibilty layer.
+ * @return object compatibilty
+ */
+
+ acf.newCompatibility = function( instance, compatibilty ){
+
+ // defaults
+ compatibilty = compatibilty || {};
+
+ // inherit __proto_-
+ compatibilty.__proto__ = instance.__proto__;
+
+ // inject
+ instance.__proto__ = compatibilty;
+
+ // reference
+ instance.compatibility = compatibilty;
+
+ // return
+ return compatibilty;
+ };
+
+ /**
+ * acf.getCompatibility
+ *
+ * Returns the compatibility layer for a given instance
+ *
+ * @date 13/3/18
+ * @since 5.6.9
+ *
+ * @param object instance The object to look in.
+ * @return object|null compatibility The compatibility object or null on failure.
+ */
+
+ acf.getCompatibility = function( instance ) {
+ return instance.compatibility || null;
+ };
+
+ /**
+ * acf (compatibility)
+ *
+ * Compatibility layer for the acf object
+ *
+ * @date 15/2/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return void
+ */
+
+ var _acf = acf.newCompatibility(acf, {
+
+ // storage
+ l10n: {},
+ o: {},
+ fields: {},
+
+ // changed function names
+ update: acf.set,
+ add_action: acf.addAction,
+ remove_action: acf.removeAction,
+ do_action: acf.doAction,
+ add_filter: acf.addFilter,
+ remove_filter: acf.removeFilter,
+ apply_filters: acf.applyFilters,
+ parse_args: acf.parseArgs,
+ disable_el: acf.disable,
+ disable_form: acf.disable,
+ enable_el: acf.enable,
+ enable_form: acf.enable,
+ update_user_setting: acf.updateUserSetting,
+ prepare_for_ajax: acf.prepareForAjax,
+ is_ajax_success: acf.isAjaxSuccess,
+ remove_el: acf.remove,
+ remove_tr: acf.remove,
+ str_replace: acf.strReplace,
+ render_select: acf.renderSelect,
+ get_uniqid: acf.uniqid,
+ serialize_form: acf.serialize,
+ esc_html: acf.strEscape,
+ str_sanitize: acf.strSanitize,
+
+ });
+
+ _acf._e = function( k1, k2 ){
+
+ // defaults
+ k1 = k1 || '';
+ k2 = k2 || '';
+
+ // compability
+ var compatKey = k2 ? k1 + '.' + k2 : k1;
+ var compats = {
+ 'image.select': 'Select Image',
+ 'image.edit': 'Edit Image',
+ 'image.update': 'Update Image'
+ };
+ if( compats[compatKey] ) {
+ return acf.__(compats[compatKey]);
+ }
+
+ // try k1
+ var string = this.l10n[ k1 ] || '';
+
+ // try k2
+ if( k2 ) {
+ string = string[ k2 ] || '';
+ }
+
+ // return
+ return string;
+ };
+
+ _acf.get_selector = function( s ) {
+
+ // vars
+ var selector = '.acf-field';
+
+ // bail early if no search
+ if( !s ) {
+ return selector;
+ }
+
+ // compatibility with object
+ if( $.isPlainObject(s) ) {
+ if( $.isEmptyObject(s) ) {
+ return selector;
+ } else {
+ for( var k in s ) { s = s[k]; break; }
+ }
+ }
+
+ // append
+ selector += '-' + s;
+
+ // replace underscores (split/join replaces all and is faster than regex!)
+ selector = acf.strReplace('_', '-', selector);
+
+ // remove potential double up
+ selector = acf.strReplace('field-field-', 'field-', selector);
+
+ // return
+ return selector;
+ };
+
+ _acf.get_fields = function( s, $el, all ){
+
+ // args
+ var args = {
+ is: s || '',
+ parent: $el || false,
+ suppressFilters: all || false,
+ };
+
+ // change 'field_123' to '.acf-field-123'
+ if( args.is ) {
+ args.is = this.get_selector( args.is );
+ }
+
+ // return
+ return acf.findFields(args);
+ };
+
+ _acf.get_field = function( s, $el ){
+
+ // get fields
+ var $fields = this.get_fields.apply(this, arguments);
+
+ // return
+ if( $fields.length ) {
+ return $fields.first();
+ } else {
+ return false;
+ }
+ };
+
+ _acf.get_closest_field = function( $el, s ){
+ return $el.closest( this.get_selector(s) );
+ };
+
+ _acf.get_field_wrap = function( $el ){
+ return $el.closest( this.get_selector() );
+ };
+
+ _acf.get_field_key = function( $field ){
+ return $field.data('key');
+ };
+
+ _acf.get_field_type = function( $field ){
+ return $field.data('type');
+ };
+
+ _acf.get_data = function( $el, defaults ){
+ return acf.parseArgs( $el.data(), defaults );
+ };
+
+ _acf.maybe_get = function( obj, key, value ){
+
+ // default
+ if( value === undefined ) {
+ value = null;
+ }
+
+ // get keys
+ keys = String(key).split('.');
+
+ // acf.isget
+ for( var i = 0; i < keys.length; i++ ) {
+ if( !obj.hasOwnProperty(keys[i]) ) {
+ return value;
+ }
+ obj = obj[ keys[i] ];
+ }
+ return obj;
+ };
+
+
+ /**
+ * hooks
+ *
+ * Modify add_action and add_filter functions to add compatibility with changed $field parameter
+ * Using the acf.add_action() or acf.add_filter() functions will interpret new field parameters as jQuery $field
+ *
+ * @date 12/5/18
+ * @since 5.6.9
+ *
+ * @param void
+ * @return void
+ */
+
+ var compatibleArgument = function( arg ){
+ return ( arg instanceof acf.Field ) ? arg.$el : arg;
+ };
+
+ var compatibleArguments = function( args ){
+ return acf.arrayArgs( args ).map( compatibleArgument );
+ }
+
+ var compatibleCallback = function( origCallback ){
+ return function(){
+
+ // convert to compatible arguments
+ if( arguments.length ) {
+ var args = compatibleArguments(arguments);
+
+ // add default argument for 'ready', 'append' and 'load' events
+ } else {
+ var args = [ $(document) ];
+ }
+
+ // return
+ return origCallback.apply(this, args);
+ }
+ }
+
+ _acf.add_action = function( action, callback, priority, context ){
+
+ // handle multiple actions
+ var actions = action.split(' ');
+ var length = actions.length;
+ if( length > 1 ) {
+ for( var i = 0; i < length; i++) {
+ action = actions[i];
+ _acf.add_action.apply(this, arguments);
+ }
+ return this;
+ }
+
+ // single
+ var callback = compatibleCallback(callback);
+ return acf.addAction.apply(this, arguments);
+ };
+
+ _acf.add_filter = function( action, callback, priority, context ){
+ var callback = compatibleCallback(callback);
+ return acf.addFilter.apply(this, arguments);
+ };
+
+ /*
+ * acf.model
+ *
+ * This model acts as a scafold for action.event driven modules
+ *
+ * @type object
+ * @date 8/09/2014
+ * @since 5.0.0
+ *
+ * @param (object)
+ * @return (object)
+ */
+
+ _acf.model = {
+ actions: {},
+ filters: {},
+ events: {},
+ extend: function( args ){
+
+ // extend
+ var model = $.extend( {}, this, args );
+
+ // setup actions
+ $.each(model.actions, function( name, callback ){
+ model._add_action( name, callback );
+ });
+
+ // setup filters
+ $.each(model.filters, function( name, callback ){
+ model._add_filter( name, callback );
+ });
+
+ // setup events
+ $.each(model.events, function( name, callback ){
+ model._add_event( name, callback );
+ });
+
+ // return
+ return model;
+ },
+
+ _add_action: function( name, callback ) {
+
+ // split
+ var model = this,
+ data = name.split(' ');
+
+ // add missing priority
+ var name = data[0] || '',
+ priority = data[1] || 10;
+
+ // add action
+ acf.add_action(name, model[ callback ], priority, model);
+
+ },
+
+ _add_filter: function( name, callback ) {
+
+ // split
+ var model = this,
+ data = name.split(' ');
+
+ // add missing priority
+ var name = data[0] || '',
+ priority = data[1] || 10;
+
+ // add action
+ acf.add_filter(name, model[ callback ], priority, model);
+ },
+
+ _add_event: function( name, callback ) {
+
+ // vars
+ var model = this,
+ i = name.indexOf(' '),
+ event = (i > 0) ? name.substr(0,i) : name,
+ selector = (i > 0) ? name.substr(i+1) : '';
+
+ // event
+ var fn = function( e ){
+
+ // append $el to event object
+ e.$el = $(this);
+
+ // append $field to event object (used in field group)
+ if( acf.field_group ) {
+ e.$field = e.$el.closest('.acf-field-object');
+ }
+
+ // event
+ if( typeof model.event === 'function' ) {
+ e = model.event( e );
+ }
+
+ // callback
+ model[ callback ].apply(model, arguments);
+
+ };
+
+ // add event
+ if( selector ) {
+ $(document).on(event, selector, fn);
+ } else {
+ $(document).on(event, fn);
+ }
+ },
+
+ get: function( name, value ){
+
+ // defaults
+ value = value || null;
+
+ // get
+ if( typeof this[ name ] !== 'undefined' ) {
+ value = this[ name ];
+ }
+
+ // return
+ return value;
+ },
+
+ set: function( name, value ){
+
+ // set
+ this[ name ] = value;
+
+ // function for 3rd party
+ if( typeof this[ '_set_' + name ] === 'function' ) {
+ this[ '_set_' + name ].apply(this);
+ }
+
+ // return for chaining
+ return this;
+ }
+ };
+
+ /*
+ * field
+ *
+ * This model sets up many of the field's interactions
+ *
+ * @type function
+ * @date 21/02/2014
+ * @since 3.5.1
+ *
+ * @param n/a
+ * @return n/a
+ */
+
+ _acf.field = acf.model.extend({
+ type: '',
+ o: {},
+ $field: null,
+ _add_action: function( name, callback ) {
+
+ // vars
+ var model = this;
+
+ // update name
+ name = name + '_field/type=' + model.type;
+
+ // add action
+ acf.add_action(name, function( $field ){
+
+ // focus
+ model.set('$field', $field);
+
+ // callback
+ model[ callback ].apply(model, arguments);
+ });
+ },
+
+ _add_filter: function( name, callback ) {
+
+ // vars
+ var model = this;
+
+ // update name
+ name = name + '_field/type=' + model.type;
+
+ // add action
+ acf.add_filter(name, function( $field ){
+
+ // focus
+ model.set('$field', $field);
+
+ // callback
+ model[ callback ].apply(model, arguments);
+ });
+ },
+
+ _add_event: function( name, callback ) {
+
+ // vars
+ var model = this,
+ event = name.substr(0,name.indexOf(' ')),
+ selector = name.substr(name.indexOf(' ')+1),
+ context = acf.get_selector(model.type);
+
+ // add event
+ $(document).on(event, context + ' ' + selector, function( e ){
+
+ // vars
+ var $el = $(this);
+ var $field = acf.get_closest_field( $el, model.type );
+
+ // bail early if no field
+ if( !$field.length ) return;
+
+ // focus
+ if( !$field.is(model.$field) ) {
+ model.set('$field', $field);
+ }
+
+ // append to event
+ e.$el = $el;
+ e.$field = $field;
+
+ // callback
+ model[ callback ].apply(model, [e]);
+ });
+ },
+
+ _set_$field: function(){
+
+ // callback
+ if( typeof this.focus === 'function' ) {
+ this.focus();
+ }
+ },
+
+ // depreciated
+ doFocus: function( $field ){
+ return this.set('$field', $field);
+ }
+ });
+
+
+ /**
+ * validation
+ *
+ * description
+ *
+ * @date 15/2/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ var _validation = acf.newCompatibility(acf.validation, {
+ remove_error: function( $field ){
+ acf.getField( $field ).removeError();
+ },
+ add_warning: function( $field, message ){
+ acf.getField( $field ).showNotice({
+ text: message,
+ type: 'warning',
+ timeout: 1000
+ });
+ },
+ fetch: acf.validateForm,
+ enableSubmit: acf.enableSubmit,
+ disableSubmit: acf.disableSubmit,
+ showSpinner: acf.showSpinner,
+ hideSpinner: acf.hideSpinner,
+ unlockForm: acf.unlockForm,
+ lockForm: acf.lockForm
+ });
+
+
+ /**
+ * tooltip
+ *
+ * description
+ *
+ * @date 15/2/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ _acf.tooltip = {
+
+ tooltip: function( text, $el ){
+
+ var tooltip = acf.newTooltip({
+ text: text,
+ target: $el
+ });
+
+ // return
+ return tooltip.$el;
+ },
+
+ temp: function( text, $el ){
+
+ var tooltip = acf.newTooltip({
+ text: text,
+ target: $el,
+ timeout: 250
+ });
+ },
+
+ confirm: function( $el, callback, text, button_y, button_n ){
+
+ var tooltip = acf.newTooltip({
+ confirm: true,
+ text: text,
+ target: $el,
+ confirm: function(){
+ callback(true);
+ },
+ cancel: function(){
+ callback(false);
+ }
+ });
+ },
+
+ confirm_remove: function( $el, callback ){
+
+ var tooltip = acf.newTooltip({
+ confirmRemove: true,
+ target: $el,
+ confirm: function(){
+ callback(true);
+ },
+ cancel: function(){
+ callback(false);
+ }
+ });
+ },
+ };
+
+ /**
+ * tooltip
+ *
+ * description
+ *
+ * @date 15/2/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ _acf.media = new acf.Model({
+ activeFrame: false,
+ actions: {
+ 'new_media_popup': 'onNewMediaPopup'
+ },
+
+ frame: function(){
+ return this.activeFrame;
+ },
+
+ onNewMediaPopup: function( popup ){
+ this.activeFrame = popup.frame;
+ },
+
+ popup: function( props ){
+
+ // update props
+ if( props.mime_types ) {
+ props.allowedTypes = props.mime_types;
+ }
+ if( props.id ) {
+ props.attachment = props.id;
+ }
+
+ // new
+ var popup = acf.newMediaPopup( props );
+
+ // append
+/*
+ if( props.selected ) {
+ popup.selected = props.selected;
+ }
+*/
+
+ // return
+ return popup.frame;
+ }
+ });
+
+
+ /**
+ * Select2
+ *
+ * description
+ *
+ * @date 11/6/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ _acf.select2 = {
+ init: function( $select, args, $field ){
+
+ // compatible args
+ if( args.allow_null ) {
+ args.allowNull = args.allow_null;
+ }
+ if( args.ajax_action ) {
+ args.ajaxAction = args.ajax_action;
+ }
+ if( $field ) {
+ args.field = acf.getField($field);
+ }
+
+ // return
+ return acf.newSelect2( $select, args );
+ },
+
+ destroy: function( $select ){
+ return acf.getInstance( $select ).destroy();
+
+ },
+ };
+
+ /**
+ * postbox
+ *
+ * description
+ *
+ * @date 11/6/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ _acf.postbox = {
+ render: function( args ){
+
+ // compatible args
+ if( args.edit_url ) {
+ args.editLink = args.edit_url;
+ }
+ if( args.edit_title ) {
+ args.editTitle = args.edit_title;
+ }
+
+ // return
+ return acf.newPostbox( args );
+ }
+ };
+
+ /**
+ * acf.screen
+ *
+ * description
+ *
+ * @date 11/6/18
+ * @since 5.6.9
+ *
+ * @param type $var Description. Default.
+ * @return type Description.
+ */
+
+ acf.newCompatibility(acf.screen, {
+ update: function(){
+ return this.set.apply(this, arguments);
+ },
+ fetch: acf.screen.check
+ });
+ _acf.ajax = acf.screen;
+
})(jQuery);
\ No newline at end of file
diff --git a/assets/build/js/acf.js b/assets/build/js/acf.js
index 7ed74e0..e1f08e9 100644
--- a/assets/build/js/acf.js
+++ b/assets/build/js/acf.js
@@ -1,2263 +1,2375 @@
-(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('') );
-
- /**
- * 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('') ) );
-
- /**
- * 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 ') );
- //console.log( acf.escHtml( acf.strEscape('') ) );
- //console.log( acf.escHtml( '' ) );
-
- /**
- * 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();
- };
- /**
- * 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 = $(' '); // 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(' ');
- };
-
- 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('
');
- };
-
- 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);
+(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;
+ };
- 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.
- */
+ /**
+ * 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('') );
- 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.
- */
+ /**
+ * 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('') ) );
+ /**
+ * 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;
- 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.
- */
+ /**
+ * Encodes ') );
+ //console.log( acf.escHtml( acf.strEscape('') ) );
+ //console.log( acf.escHtml( '' ) );
- 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.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.getXhrError = function (xhr) {
- if (xhr.responseJSON && xhr.responseJSON.message) {
- return xhr.responseJSON.message;
- } else if (xhr.statusText) {
- return xhr.statusText;
- }
+ /**
+ * 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 = $(' ');
+
+ // 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(' ');
+ }
+
+ 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('
');
+ };
+
+ 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 = $input[0].files.length ? acf.isget($input[0].files, 0) : false;
+ 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 += '' + crawl( item.children ) + ' ';
+
+ // option
+ } else {
+ itemsHtml += '' + acf.strEscape(text) + ' ';
+ }
+ });
+
+ // 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);
+ }
+ }
- 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 += '' + crawl(item.children) + ' '; // option
- } else {
- itemsHtml += '' + acf.strEscape(text) + ' ';
- }
- }); // 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
@@ -2266,1874 +2378,2072 @@
* @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;
+ }
- 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);
- };
- }
- /**
- * Returns true if value is a number or a numeric string.
- *
- * @date 30/11/20
- * @since 5.9.4
- * @link https://stackoverflow.com/questions/9716468/pure-javascript-a-function-like-jquerys-isnumeric/9716488#9716488
- *
- * @param mixed n The variable being evaluated.
- * @return bool.
- */
-
-
- acf.isNumeric = function (n) {
- return !isNaN(parseFloat(n)) && isFinite(n);
- };
- /**
- * 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 () {
- // Use timeout to ensure action runs after Gutenberg has modified DOM elements during "DOMContentLoaded".
- setTimeout(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.
+ // Remove class after $wait amount of time.
+ var fadeTime = 250;
+ setTimeout(function(){
+ $el.removeClass( '-focused' );
+ setTimeout(function(){
+ $el.removeClass( 'acf-attention' );
+ }, fadeTime);
+ }, wait);
+ };
+
+ /**
+ * Description
*
- * @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.
+ * @date 05/05/2020
+ * @since 5.9.0
*
- * @param action The action to remove
- * @param [callback] Callback function to remove
+ * @param type Var Description.
+ * @return type Description.
*/
+ acf.onFocus = function( $el, callback ){
+ // Only run once per element.
+ // if( $el.data('acf.onFocus') ) {
+ // return false;
+ // }
- 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);
+ // 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 );
}
- }
- } else {
- for (i = handlers.length; i--;) {
- var handler = handlers[i];
-
- if (handler.callback === callback && handler.context === context) {
- handlers.splice(i, 1);
+ };
+ 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;
}
- }
- }
- }
- }
- /**
- * 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;
- };
+ 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);
+ };
+
+ }
+
+ /**
+ * Returns true if value is a number or a numeric string.
+ *
+ * @date 30/11/20
+ * @since 5.9.4
+ * @link https://stackoverflow.com/questions/9716468/pure-javascript-a-function-like-jquerys-isnumeric/9716488#9716488
+ *
+ * @param mixed n The variable being evaluated.
+ * @return bool.
+ */
+ acf.isNumeric = function( n ){
+ return !isNaN(parseFloat(n)) && isFinite(n);
+ }
+
+ /**
+ * 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(){
+
+ // Use timeout to ensure action runs after Gutenberg has modified DOM elements during "DOMContentLoaded".
+ setTimeout(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";
-(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 [''].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.
+ /**
+ * 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
+ };
- this.title(title);
- this.content(content);
+ /**
+ * 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 );
+ }
- if (width) {
- this.$('.acf-popup-box').css('width', width);
- }
+ return MethodsAvailable;
+ }
- if (height) {
- this.$('.acf-popup-box').css('min-height', height);
- }
+ /**
+ * 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();
- this.loading(loading); // Trigger action.
+ if( typeof action === 'string' ) {
+ _runHook( 'actions', action, args );
+ }
- 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
- */
+ return MethodsAvailable;
+ }
- acf.newPopup = function (props) {
- return new acf.models.Popup(props);
- };
+ /**
+ * 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 [
+ ''
+ ].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();
+ },
-(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 = $(['', '
', '
', '
' + title + ' ', ' ', '', '
' + content + '
', '
' + toolbar + '
', '
', '
', '
'].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);
- };
+ 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) {
- 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');
- }
- });
+(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 = $([
+ '',
+ '
',
+ '
',
+ '
' + title + ' ',
+ ' ',
+ '',
+ '
' + content + '
',
+ '
' + toolbar + '
',
+ '
',
+ '
',
+ '
'
+ ].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 Notice = acf.Model.extend({
- data: {
- text: '',
- type: '',
- timeout: 0,
- dismiss: true,
- target: false,
- close: function () {}
- },
- events: {
- 'click .acf-notice-dismiss': 'onClickClose'
- },
- tmpl: function () {
- return '
';
- },
- 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('' + this.get('text') + '
'); // close
-
- if (this.get('dismiss')) {
- this.$el.append(' ');
- 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);
- }
- }
- });
+(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) {
- 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 '
';
- },
- 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, '' + textConfirm + ' ', '' + textCancel + ' '].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'));
- }
- });
+(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 '
';
+ },
+
+ 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( '' + this.get('text') + '
' );
+
+ // close
+ if( this.get('dismiss') ) {
+ this.$el.append(' ');
+ 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 '
';
+ },
+
+ 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,
+ '' + textConfirm + ' ',
+ '' + textCancel + ' '
+ ].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);
\ No newline at end of file
diff --git a/assets/build/js/acf.min.js b/assets/build/js/acf.min.js
index 1a933c5..3892819 100644
--- a/assets/build/js/acf.min.js
+++ b/assets/build/js/acf.min.js
@@ -1 +1 @@
-!function(s,r){var c={};(window.acf=c).data={},c.get=function(t){return this.data[t]||null},c.has=function(t){return null!==this.get(t)},c.set=function(t,e){return this.data[t]=e,this};var n=0;c.uniqueId=function(t){var e=++n+"";return t?t+e:e},c.uniqueArray=function(t){return t.filter(function(t,e,n){return n.indexOf(t)===e})};var i="";c.uniqid=function(t,e){void 0===t&&(t="");function n(t,e){return e<(t=parseInt(t,10).toString(16)).length?t.slice(t.length-e):e>t.length?Array(e-t.length+1).join("0")+t:t}return i=i||Math.floor(123456789*Math.random()),i++,t=t,t+=n(parseInt((new Date).getTime()/1e3,10),8),t+=n(i,5),e&&(t+=(10*Math.random()).toFixed(8).toString()),t},c.strReplace=function(t,e,n){return n.split(t).join(e)},c.strCamelCase=function(t){t=t.match(/([a-zA-Z0-9]+)/g);return t?t.map(function(t,e){var n=t.charAt(0);return(0===e?n.toLowerCase():n.toUpperCase())+t.slice(1)}).join(""):""},c.strPascalCase=function(t){t=c.strCamelCase(t);return t.charAt(0).toUpperCase()+t.slice(1)},c.strSlugify=function(t){return c.strReplace("_","-",t.toLowerCase())},c.strSanitize=function(t){var e={"À":"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"," ":"_","'":"","?":"","/":"","\\":"",".":"",",":"","`":"",">":"","<":"",'"':"","[":"","]":"","|":"","{":"","}":"","(":"",")":""};return t=(t=t.replace(/\W/g,function(t){return e[t]!==r?e[t]:t})).toLowerCase()},c.strMatch=function(t,e){for(var n=0,i=Math.min(t.length,e.length),o=0;o":">",'"':""","'":"'"};return(""+t).replace(/[&<>"']/g,function(t){return e[t]})},c.strUnescape=function(t){var e={"&":"&","<":"<",">":">",""":'"',"'":"'"};return(""+t).replace(/&|<|>|"|'/g,function(t){return e[t]})},c.escAttr=c.strEscape,c.escHtml=function(t){return(""+t).replace(/").html(t).text()},c.parseArgs=function(t,e){return s.extend({},e="object"!=typeof e?{}:e,t="object"!=typeof t?{}:t)},window.acfL10n==r&&(acfL10n={}),c.__=function(t){return acfL10n[t]||t},c._x=function(t,e){return acfL10n[t+"."+e]||acfL10n[t]||t},c._n=function(t,e,n){return 1==n?c.__(t):c.__(e)},c.isArray=function(t){return Array.isArray(t)},c.isObject=function(t){return"object"==typeof t};c.serialize=function(t,e){var n={},i=c.serializeArray(t);e!==r&&(i=i.filter(function(t){return 0===t.name.indexOf(e)}).map(function(t){return t.name=t.name.slice(e.length),t}));for(var o=0;o');var s=e.parent();e.css({height:n,width:i,margin:o,position:"absolute"}),setTimeout(function(){s.css({opacity:0,height:t.endHeight})},50),setTimeout(function(){e.attr("style",a),s.remove(),t.complete()},301)},u=function(t){var e=t.target,n=e.height(),i=e.children().length,o=s(' ');e.addClass("acf-remove-element"),setTimeout(function(){e.html(o)},251),setTimeout(function(){e.removeClass("acf-remove-element"),o.css({height:t.endHeight})},300),setTimeout(function(){e.remove(),t.complete()},451)};c.duplicate=function(t){t instanceof jQuery&&(t={target:t}),(t=c.parseArgs(t,{target:!1,search:"",replace:"",rename:!0,before:function(t){},after:function(t,e){},append:function(t,e){t.after(e)}})).target=t.target||t.$el;var e=t.target;t.search=t.search||e.attr("data-id"),t.replace=t.replace||c.uniqid(),t.before(e),c.doAction("before_duplicate",e);var n=e.clone();return t.rename&&c.rename({target:n,search:t.search,replace:t.replace,replacer:"function"==typeof t.rename?t.rename:null}),n.removeClass("acf-clone"),n.find(".ui-sortable").removeClass("ui-sortable"),t.after(e,n),c.doAction("after_duplicate",e,n),t.append(e,n),c.doAction("duplicate",e,n),c.doAction("append",n),n},c.rename=function(i){i instanceof jQuery&&(i={target:i});var t=(i=c.parseArgs(i,{target:!1,destructive:!1,search:"",replace:"",replacer:null})).target;i.search||(i.search=t.attr("data-id")),i.replace||(i.replace=c.uniqid("acf")),i.replacer||(i.replacer=function(t,e,n,i){return e.replace(n,i)});function e(n){return function(t,e){return i.replacer(n,e,i.search,i.replace)}}var n;return i.destructive?(n=c.strReplace(i.search,i.replace,t.outerHTML()),t.replaceWith(n)):(t.attr("data-id",i.replace),t.find('[id*="'+i.search+'"]').attr("id",e("id")),t.find('[for*="'+i.search+'"]').attr("for",e("for")),t.find('[name*="'+i.search+'"]').attr("name",e("name"))),t},c.prepareForAjax=function(t){return t.nonce=c.get("nonce"),t.post_id=c.get("post_id"),c.has("language")&&(t.lang=c.get("language")),t=c.applyFilters("prepare_for_ajax",t)},c.startButtonLoading=function(t){t.prop("disabled",!0),t.after(' ')},c.stopButtonLoading=function(t){t.prop("disabled",!1),t.next(".acf-loading").remove()},c.showLoading=function(t){t.append('
')},c.hideLoading=function(t){t.children(".acf-loading-overlay").remove()},c.updateUserSetting=function(t,e){e={action:"acf/ajax/user_setting",name:t,value:e};s.ajax({url:c.get("ajaxurl"),data:c.prepareForAjax(e),type:"post",dataType:"html"})},c.val=function(t,e,n){var i=t.val();return e!==i&&(t.val(e),t.is("select")&&null===t.val()?(t.val(i),!1):(!0!==n&&t.trigger("change"),!0))},c.show=function(t,e){return e&&c.unlock(t,"hidden",e),!c.isLocked(t,"hidden")&&(!!t.hasClass("acf-hidden")&&(t.removeClass("acf-hidden"),!0))},c.hide=function(t,e){return e&&c.lock(t,"hidden",e),!t.hasClass("acf-hidden")&&(t.addClass("acf-hidden"),!0)},c.isHidden=function(t){return t.hasClass("acf-hidden")},c.isVisible=function(t){return!c.isHidden(t)};function f(t,e){return!t.hasClass("acf-disabled")&&(e&&c.unlock(t,"disabled",e),!c.isLocked(t,"disabled")&&(!!t.prop("disabled")&&(t.prop("disabled",!1),!0)))}c.enable=function(t,e){if(t.attr("name"))return f(t,e);var n=!1;return t.find("[name]").each(function(){f(s(this),e)&&(n=!0)}),n};function d(t,e){return e&&c.lock(t,"disabled",e),!t.prop("disabled")&&(t.prop("disabled",!0),!0)}c.disable=function(t,e){if(t.attr("name"))return d(t,e);var n=!1;return t.find("[name]").each(function(){d(s(this),e)&&(n=!0)}),n},c.isset=function(t){for(var e=1;e'+r(t.children)+"":i+='"+c.strEscape(e)+" "}),i};return t.html(r(e)),-1e.priority;)t[n]=t[n-1],--n;t[n]=e}return t}(o)):[i];s[t][e]=o}function i(t,e,n){var i=s[t][e];if(!i)return"filters"===t&&n[0];var o=0,r=i.length;if("filters"===t)for(;o