PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields: Extended / 0.9.2.7
Advanced Custom Fields: Extended v0.9.2.7
0.9.2.7 0.9.2.6 0.9.2.5 0.8.6 0.8.6.1 0.8.6.3 0.8.6.5 0.8.6.6 0.8.6.7 0.8.6.8 0.8.6.9 0.8.7 0.8.7.1 0.8.7.2 0.8.7.3 0.8.7.4 0.8.7.5 0.8.7.6 0.8.8 0.8.8.1 0.8.8.10 0.8.8.11 0.8.8.2 0.8.8.3 0.8.8.4 0.8.8.5 0.8.8.6 0.8.8.7 0.8.8.8 0.8.8.9 0.8.9 0.8.9.1 0.8.9.2 0.8.9.3 0.8.9.4 0.8.9.5 0.9 0.9.0.1 0.9.0.2 0.9.0.3 0.9.0.4 0.9.0.5 0.9.0.6 0.9.0.7 0.9.0.8 0.9.0.9 0.9.1 0.9.1.1 0.9.2 0.9.2.1 0.9.2.2 0.9.2.3 0.9.2.4 trunk 0.5 0.5.1 0.5.2 0.5.2.1 0.5.2.3 0.5.5 0.5.5.1 0.5.8 0.5.8.1 0.6 0.6.0.1 0.6.0.2 0.6.1 0.6.3 0.6.5 0.6.7 0.6.7.2 0.7 0.7.0.3 0.7.5 0.7.5.5 0.7.8 0.7.9 0.7.9.3 0.7.9.4 0.7.9.9.8 0.7.9.9.9 0.8 0.8.1 0.8.2 0.8.3 0.8.3.1 0.8.4 0.8.4.1 0.8.4.5 0.8.4.6 0.8.5 0.8.5.5
acf-extended / assets / js / acfe.js
acf-extended / assets / js Last commit date
acfe-admin.js 9 months ago acfe-admin.min.js 9 months ago acfe-field-group.js 3 months ago acfe-field-group.min.js 3 months ago acfe-input.js 3 months ago acfe-input.min.js 3 months ago acfe-ui.js 7 months ago acfe-ui.min.js 7 months ago acfe.js 3 months ago acfe.min.js 3 months ago
acfe.js
2622 lines
1 (function($) {
2
3 if (typeof acf === 'undefined') {
4 return;
5 }
6
7 /**
8 * acfe
9 *
10 * @type {{}}
11 */
12 window.acfe = {};
13
14 })(jQuery);
15 (function($) {
16
17 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
18 return;
19 }
20
21 /**
22 * acfe.getArray
23 *
24 * Forces val as an array, also allows integer 0
25 *
26 * @param val
27 * @returns {*[]}
28 */
29 acfe.getArray = function(val) {
30 val = val === 0 ? '0' : val;
31 return [].concat(val || []);
32 };
33
34
35 /**
36 * acfe.getObject
37 *
38 * Forces val as an object
39 *
40 * @param val
41 * @returns {*[]}
42 */
43 acfe.getObject = function(val) {
44 return acf.parseArgs(val);
45 };
46
47
48 /**
49 * acfe.extractVar
50 *
51 * Extracts a value from an object
52 *
53 * @param obj
54 * @param prop
55 * @param def
56 * @returns {null|*}
57 */
58 acfe.extractVar = function(obj, prop, def = null) {
59
60 var value = obj[prop];
61 delete obj[prop];
62
63 if (acfe.isUndefined(value)) {
64 return def;
65 }
66
67 return value;
68
69 }
70
71
72 /**
73 * acfe.extractVars
74 *
75 * Extracts multiple values from an object
76 *
77 * @param obj
78 * @param props
79 * @returns {{}}
80 */
81 acfe.extractVars = function(obj, ...props) {
82
83 var value = {};
84 for (var prop of props) {
85
86 var extract = acfe.extractVar(obj, prop, '!!undefined!!');
87
88 if (extract !== '!!undefined!!') {
89 value[prop] = extract;
90 }
91
92 }
93
94 return value;
95
96 }
97
98
99 /**
100 * acfe.getEntries
101 *
102 * Get object entries to use in for(var [x, y] of obj){}
103 *
104 * @param obj
105 * @returns {[string, unknown][]}
106 */
107 acfe.getEntries = function(obj) {
108 return Object.entries(obj);
109 }
110
111
112 /**
113 * acfe.inArray
114 *
115 * @param v1
116 * @param array
117 * @param strict
118 * @returns {boolean}
119 */
120 acfe.inArray = function(v1, array, strict = false) {
121
122 if (!strict) {
123
124 v1 = acfe.getString(v1);
125 array = array.map(function(v2) {
126 return acfe.getString(v2);
127 });
128
129 }
130
131 for (var i = 0; i < array.length; i++) {
132 if (array[i] === v1) {
133 return true;
134 }
135 }
136
137 return false;
138
139 };
140
141
142 /**
143 * acfe.arrayGet
144 *
145 * Get array/object value using dot notation
146 *
147 * https://github.com/callmecavs/dotnot/blob/master/src/dotnot.js
148 *
149 * @param obj
150 * @param path
151 * @param def
152 * @returns {null|*}
153 */
154 acfe.arrayGet = function(obj, path, def = null) {
155
156 // get path array
157 path = acfe.normalizePath(path);
158
159 // length of path array
160 var len = path.length;
161
162 // loop through path updating the reference to child objects
163 var current = obj;
164 var name;
165
166 for (var index = 0; index < len; index++) {
167
168 // current key name
169 name = path[index];
170
171 // stop searching if a child object is missing
172 if (acfe.isUndefined(current[name])) {
173 return def;
174 }
175
176 current = current[name];
177 }
178
179 return current;
180
181 }
182
183
184 /**
185 * acfe.arrayHas
186 *
187 * Check array/object has key using dot notation
188 * '!!undefined!!' is workaround allowing 'null' to be considered as a valid value
189 *
190 * @param obj
191 * @param path
192 * @returns {*}
193 */
194 acfe.arrayHas = function(obj, path) {
195 return acfe.arrayGet(obj, path, '!!undefined!!') !== '!!undefined!!';
196 }
197
198
199 /**
200 * acfe.arraySet
201 *
202 * Set array/object value using dot notation
203 *
204 * https://github.com/callmecavs/dotnot/blob/master/src/dotnot.js
205 *
206 * @param obj
207 * @param path
208 * @param val
209 */
210 acfe.arraySet = function(obj, path, val) {
211
212 // get path array
213 path = acfe.normalizePath(path);
214
215 // length of path array
216 var len = path.length;
217
218 // loop through path updating the reference to child objects
219 var current = obj;
220 var name;
221
222 for (var index = 0; index < len; index++) {
223
224 // current key name
225 name = path[index];
226
227 // set value on last key
228 if (index === len - 1) {
229 current[name] = val;
230
231 } else if (current[name]) {
232
233 if (!acfe.isObject(current[name])) {
234 current[name] = {};
235 }
236
237 current = current[name];
238
239 } else {
240 current[name] = {};
241 current = current[name];
242
243 }
244
245 }
246
247 // re-index array
248 obj = acfe.arrayReindex(obj);
249
250 // return
251 return obj;
252
253 }
254
255
256 /**
257 * acfe.arrayDelete
258 *
259 * Delete array/object key via dot notation
260 *
261 * https://github.com/callmecavs/dotnot/blob/master/src/dotnot.js
262 *
263 * @param obj
264 * @param path
265 * @returns {*}
266 */
267 acfe.arrayDelete = function(obj, path) {
268
269 // get path array
270 path = acfe.normalizePath(path);
271
272 // length of path array
273 var len = path.length;
274
275 // loop through path updating the reference to child objects
276 var current = obj;
277 var name;
278
279 for (var index = 0; index < len; index++) {
280
281 // current key name
282 name = path[index];
283
284 // set value on last key
285 if (index === len - 1) {
286 delete current[name];
287 } else {
288 current = current[name] || {};
289 }
290
291 }
292
293 // re-index array
294 obj = acfe.arrayReindex(obj);
295
296 // return
297 return obj;
298
299 }
300
301
302 /**
303 * acfe.arrayPluck
304 *
305 * '!!undefined!!' is workaround allowing 'null' to be considered as a valid value
306 *
307 * @param obj
308 * @param path
309 * @param id
310 * @returns {*[]}
311 */
312 acfe.arrayPluck = function(obj, path, id = false) {
313
314 // vars
315 var idPath;
316 var idObj = {};
317 var collect = [];
318
319 // prepare id
320 if (id) {
321
322 idPath = path.split('.');
323 idPath.pop();
324 idPath.push(id);
325 idPath = idPath.join('.');
326
327 }
328
329 // loop
330 for (var row of obj) {
331
332 var result = acfe.arrayGet(row, path, '!!undefined!!');
333
334 // bail early
335 if (result === '!!undefined!!') {
336 continue;
337 }
338
339 // push to collection
340 collect.push(result);
341
342 if (id) {
343 var key = acfe.arrayGet(row, idPath, '!!undefined!!');
344
345 if (key !== '!!undefined!!') {
346 idObj[key] = result;
347 }
348 }
349
350 }
351
352 // collect id
353 if (id) {
354 collect = idObj;
355 }
356
357 // return
358 return collect;
359
360 }
361
362
363 /**
364 * acfe.normalizePath
365 *
366 * Converts a dot notation path as array
367 *
368 * @param path
369 * @returns {*[]|string[]}
370 */
371 acfe.normalizePath = function(path) {
372
373 // convert to string
374 path = acfe.getString(path);
375
376 // split dot notation
377 path = path.split('.');
378
379 // return
380 return path;
381
382 }
383
384
385 /**
386 * acfe.arrayReindex
387 *
388 * Re-index array after delete usage
389 *
390 * @param obj
391 * @returns {*}
392 */
393 acfe.arrayReindex = function(obj) {
394
395 // filter
396 if (acfe.isArray(obj)) {
397 obj = obj.filter(function(val) {
398 return !acfe.isUndefined(val);
399 });
400 }
401
402 // return
403 return obj;
404
405 }
406
407 })(jQuery);
408 (function($) {
409
410 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
411 return;
412 }
413
414
415 /**
416 * acfe.isACF
417 *
418 * @param min
419 * @param max
420 *
421 * @returns {false|0|boolean|number}
422 */
423 acfe.isACF = function(min, max) {
424
425 // get version
426 var version = String(acf.get('acf_version'));
427 version = version.replace(/[^0-9.].*$/, ''); // remove any non-numeric characters (e.g. -beta)
428
429 // check only one version
430 if (typeof max === 'undefined') {
431 return acfe.versionCompare(version, '>=', min);
432 }
433
434 // check both versions
435 return acfe.versionCompare(version, '>=', min) && acfe.versionCompare(version, '<', max);
436
437 }
438
439
440 /**
441 * acfe.isWP
442 *
443 * @param min
444 * @param max
445 *
446 * @returns {false|0|boolean|number}
447 */
448 acfe.isWP = function(min, max) {
449
450 // get version
451 var version = String(acf.get('wp_version'));
452 version = version.replace(/[^0-9.].*$/, ''); // remove any non-numeric characters (e.g. -beta)
453
454 // check only one version
455 if (typeof max === 'undefined') {
456 return acfe.versionCompare(version, '>=', min);
457 }
458
459 // check both versions
460 return acfe.versionCompare(version, '>=', min) && acfe.versionCompare(version, '<', max);
461
462 }
463
464
465 /**
466 * acfe.isACF65
467 *
468 * Check if ACF version is 6.5+
469 *
470 * @deprecated since 0.9.2.5
471 *
472 * @returns {boolean|number}
473 */
474 acfe.isACF65 = function() {
475 acfe.deprecatedFunction('acfe.isACF65()', '0.9.2.5', "acfe.isACF('6.5')");
476 return acfe.isACF('6.5');
477 }
478
479 })(jQuery);
480 (function($) {
481
482 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
483 return;
484 }
485
486 /**
487 * acf.data.acfe
488 *
489 * @type {{}}
490 */
491 acf.data.acfe = {};
492
493
494 /**
495 * acfe.get
496 *
497 * @param name
498 * @param def
499 * @returns {*|null}
500 */
501 acfe.get = function(name = null, def = null) {
502 return name === null ? acf.data.acfe : acfe.arrayGet(acf.data.acfe, name, def);
503 };
504
505
506 /**
507 * acfe.has
508 *
509 * @param name
510 * @returns {boolean}
511 */
512 acfe.has = function(name) {
513 return acfe.arrayGet(acf.data.acfe, name) !== null;
514 };
515
516
517 /**
518 * acfe.set
519 *
520 * @param name
521 * @param value
522 * @returns {acfe}
523 */
524 acfe.set = function(name, value) {
525 acfe.arraySet(acf.data.acfe, name, value);
526 return this;
527 };
528
529 })(jQuery);
530 (function($) {
531
532 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
533 return;
534 }
535
536 /**
537 * acfe.deprecatedFunction
538 *
539 * @param fnc
540 * @param version
541 * @param replacement
542 */
543 acfe.deprecatedFunction = function(fnc, version, replacement = '') {
544
545 replacement = replacement ? '! Use ' + replacement + ' instead.' : ' with no alternative available.';
546
547 console.log('ACF Extended: ' + fnc + ' is deprecated since version ' + version + replacement);
548
549 }
550
551
552 /**
553 * acfe.deprecatedHook
554 *
555 * @param hook
556 * @param version
557 * @param replacement
558 */
559 acfe.deprecatedHook = function(hook, version, replacement = '') {
560
561 replacement = replacement ? '! Use ' + replacement + ' instead.' : ' with no alternative available.';
562
563 console.log('ACF Extended: Hook ' + hook + ' is deprecated since version ' + version + replacement);
564
565 }
566
567
568 /**
569 * acfe.applyFiltersDeprecated
570 *
571 * @param hook
572 * @param args
573 * @param version
574 * @param replacement
575 * @returns {*}
576 */
577 acfe.applyFiltersDeprecated = function(hook, args, version, replacement = '') {
578
579 // bail early
580 if (!acfe.hasFilter(hook)) {
581 return args[0];
582 }
583
584 // log deprecated
585 acfe.deprecatedHook(hook, version, replacement);
586
587 // appply filters
588 return acf.applyFilters(hook, ...args);
589
590 }
591
592
593 /**
594 * acfe.doActionDeprecated
595 *
596 * @param hook
597 * @param args
598 * @param version
599 * @param replacement
600 * @returns {*}
601 */
602 acfe.doActionDeprecated = function(hook, args, version, replacement = '') {
603
604 // bail early
605 if (!acfe.hasAction(hook)) {
606 return;
607 }
608
609 // log deprecated
610 acfe.deprecatedHook(hook, version, replacement);
611
612 // appply filters
613 return acf.doAction(hook, ...args);
614
615 }
616
617 })(jQuery);
618 (function($) {
619
620 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
621 return;
622 }
623
624 /**
625 * isFieldKey
626 *
627 * @param name
628 * @returns {boolean}
629 */
630 acfe.isFieldKey = function(name) {
631 return acfe.isString(name) && name.startsWith('field_');
632 }
633
634
635 /**
636 * acfe.isFieldName
637 *
638 * @param name
639 * @returns {boolean}
640 */
641 acfe.isFieldName = function(name) {
642 return acfe.isString(name) && !acfe.isFieldKey(name);
643 }
644
645
646 /**
647 * isGroupKey
648 *
649 * @param name
650 * @returns {boolean}
651 */
652 acfe.isGroupKey = function(name) {
653 return acfe.isString(name) && name.startsWith('group_');
654 }
655
656
657 /**
658 * acfe.getField
659 *
660 * Allow to query a single field with name, or arguments
661 *
662 * @param name
663 * @returns {[]|*}
664 */
665 acfe.getField = function(name) {
666
667 // field name
668 if (acfe.isFieldName(name)) {
669
670 return acf.getFields({
671 name: name,
672 limit: 1,
673 suppressFilters: true
674 }).shift();
675
676 // arguments
677 } else if (acfe.isObject(name)) {
678
679 name = acf.parseArgs(name, {
680 limit: 1,
681 suppressFilters: true
682 });
683
684 return acf.getFields(name).shift();
685
686 }
687
688 // default getField
689 return acf.getField(name);
690
691 };
692
693
694 /**
695 * find_fields_selector
696 *
697 * Allows to use multiple field types (array) as argument
698 *
699 * Available in ACF 6.0.
700 */
701 acf.addFilter('find_fields_selector', function(selector, args) {
702
703 // args.types
704 // allow types array
705 if (args.types && args.types.length && acfe.isArray(args.types)) {
706
707 // vars
708 var array = [];
709
710 // loop
711 for (var type of args.types) {
712 array.push(selector + '[data-type="' + type + '"]');
713 }
714
715 selector = array.join(',');
716
717 }
718
719 // return
720 return selector;
721
722 });
723
724 })(jQuery);
725 (function($) {
726
727 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
728 return;
729 }
730
731 /**
732 * storage
733 *
734 * @type {*[]}
735 */
736 var filters = [];
737
738
739 /**
740 * acfe.disableFilters
741 */
742 acfe.disableFilters = function() {
743 filters = [];
744 };
745
746
747 /**
748 * acfe.getFilters
749 *
750 * @returns {*[]}
751 */
752 acfe.getFilters = function() {
753 return filters;
754 };
755
756
757 /**
758 * acfe.isFilterEnabled
759 *
760 * @param name
761 * @returns {boolean}
762 */
763 acfe.isFilterEnabled = function(name) {
764 return filters.indexOf(name) > -1;
765 };
766
767
768 /**
769 * acfe.enableFilter
770 *
771 * @param name
772 */
773 acfe.enableFilter = function(name) {
774 if (filters.indexOf(name) === -1) {
775 filters.push(name);
776 }
777 };
778
779
780 /**
781 * acfe.disableFilter
782 *
783 * @param name
784 */
785 acfe.disableFilter = function(name) {
786 for (var i = filters.length; i--;) {
787 if (filters[i] === name) {
788 filters.splice(i, 1);
789 }
790 }
791 };
792
793 })(jQuery);
794 (function($) {
795
796 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
797 return;
798 }
799
800 /**
801 * acfe.findSubmitWrap
802 *
803 * @param $form
804 * @returns {{length}|*|jQuery|HTMLElement}
805 */
806 acfe.findSubmitWrap = function($form) {
807
808 var $wrap;
809 $form = $form || $('form');
810
811 // default post submit div
812 $wrap = $form.find('#submitdiv');
813 if ($wrap.length) {
814 return $wrap;
815 }
816
817 // 3rd party publish box
818 $wrap = $form.find('#submitpost');
819 if ($wrap.length) {
820 return $wrap;
821 }
822
823 // term, user
824 $wrap = $form.find('p.submit').last();
825 if ($wrap.length) {
826 return $wrap;
827 }
828
829 // front end form
830 $wrap = $form.find('.acf-form-submit');
831 if ($wrap.length) {
832 return $wrap;
833 }
834
835 // default
836 return $form;
837
838 };
839
840
841 /**
842 * acfe.findSubmit
843 *
844 * @param $form
845 * @returns {*|jQuery}
846 */
847 acfe.findSubmit = function($form) {
848
849 $form = $form || $('form');
850 return this.findSubmitWrap($form).find('.button, [type="submit"]');
851
852 }
853
854
855 /**
856 * acfe.findSpinner
857 *
858 * @param $form
859 * @returns {*|jQuery}
860 */
861 acfe.findSpinner = function($form) {
862
863 $form = $form || $('form');
864 return this.findSubmitWrap($form).find('.spinner, .acf-spinner');
865
866 }
867
868 })(jQuery);
869 (function($) {
870
871 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
872 return;
873 }
874
875 /**
876 * acfe.hasFilter
877 *
878 * @param hook
879 * @param callback
880 * @returns {boolean}
881 */
882 acfe.hasFilter = function(hook, callback = false) {
883 return acfe.hasHook('filters', hook, callback);
884 }
885
886
887 /**
888 * acfe.hasAction
889 *
890 * @param hook
891 * @param callback
892 * @returns {boolean}
893 */
894 acfe.hasAction = function(hook, callback = false) {
895 return acfe.hasHook('actions', hook, callback);
896 }
897
898
899 /**
900 * acfe.hasHook
901 *
902 * @param type
903 * @param hook
904 * @param callback
905 * @returns {boolean}
906 */
907 acfe.hasHook = function(type, hook, callback = false) {
908
909 // get hooks storage
910 var storage = acf.hooks.storage();
911
912 // no hooks
913 if (!acfe.arrayGet(storage[type], hook)) {
914 return false;
915 }
916
917 // no callback specified
918 if (!callback) {
919 return true;
920 }
921
922 // loop on hooks
923 for (var row of storage[type][hook]) {
924
925 // callback name found
926 if (acfe.arrayGet(row, 'callback.name') === callback) {
927 return true;
928 }
929
930 }
931
932 return false;
933
934 }
935
936 })(jQuery);
937 (function($) {
938
939 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
940 return;
941 }
942
943 /**
944 * modal initializer
945 *
946 * @type {string[]}
947 */
948 var actions = ['prepare', 'ready', 'load', 'append', 'remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload'];
949
950 actions.map(function(action) {
951
952 acf.addAction(action, function($el) {
953
954 // initialize modals
955 acfe.getModals({
956 parent: $el
957 });
958
959 });
960
961 });
962
963
964 /**
965 * acfe.getModals
966 *
967 * @param $modals
968 * @returns {*[]}
969 */
970 acfe.getModals = function($modals) {
971
972 // jquery element allowed
973 // if not jquery perform query
974 if (!acfe.isJquery($modals)) {
975 $modals = acfe.findModals($modals);
976 }
977
978 // loop
979 var modals = [];
980 $modals.each(function() {
981 var modal = acfe.getModal($(this));
982 modals.push(modal);
983 });
984
985 // return
986 return modals;
987
988 }
989
990
991 /**
992 * acfe.getModal
993 *
994 * @param $modal
995 * @param args
996 * @returns {boolean|*}
997 */
998 acfe.getModal = function($modal, args) {
999
1000 // args query
1001 if (!acfe.isJquery($modal)) {
1002 $modal = acfe.findModal($modal);
1003 }
1004
1005 // no modal found
1006 // check class just in case of unrelated element
1007 if (!$modal.length || !$modal.hasClass('acfe-modal')) {
1008 return false;
1009 }
1010
1011 // return
1012 return acfe.newModal($modal, args);
1013
1014 };
1015
1016
1017 /**
1018 * acfe.findModals
1019 *
1020 * @param args
1021 * @returns {*}
1022 */
1023 acfe.findModals = function(args) {
1024
1025 // vars
1026 var selector = '.acfe-modal';
1027 var $modals = false;
1028
1029 // args
1030 args = acf.parseArgs(args, {
1031 modal: '', // The modal's name (data-attribute).
1032 is: '', // jQuery selector to compare against.
1033 parent: false, // jQuery element to search within.
1034 sibling: false, // jQuery element to search alongside.
1035 limit: false, // The number of modals to find.
1036 open: false, // Whether to only return open modals.
1037 close: false, // Whether to only return open modals.
1038 suppressFilters: false, // Whether to allow filters to add/remove results. Default behaviour will ignore clone fields.
1039 });
1040
1041 // modal
1042 if (args.modal) {
1043 selector += '[data-modal="' + args.modal + '"]';
1044 }
1045
1046 // is
1047 if (args.is) {
1048 selector += args.is;
1049 }
1050
1051 // open
1052 if (args.open) {
1053 selector += ':visible';
1054 }
1055
1056 // close
1057 if (args.close) {
1058 selector += ':hidden';
1059 }
1060
1061 // query
1062 if (args.parent) {
1063 $modals = args.parent.find(selector);
1064 } else if (args.sibling) {
1065 $modals = args.sibling.siblings(selector);
1066 } else {
1067 $modals = $(selector);
1068 }
1069
1070 // filter
1071 if (!args.suppressFilters) {
1072 $modals = $modals.not('.acf-clone .acfe-modal');
1073 }
1074
1075 // limit
1076 if (args.limit) {
1077 $modals = $modals.slice(0, args.limit);
1078 }
1079
1080 // return
1081 return $modals;
1082
1083 };
1084
1085
1086 /**
1087 * acfe.findModal
1088 *
1089 * @param modal
1090 * @param $parent
1091 * @returns {*}
1092 */
1093 acfe.findModal = function(modal, $parent) {
1094
1095 // todo: allow args object to be passed to allow get opened/closed modals
1096 return acfe.findModals({
1097 modal: modal,
1098 limit: 1,
1099 parent: $parent,
1100 });
1101 };
1102
1103
1104 /**
1105 * acfe.findClosestModal
1106 *
1107 * @param $el
1108 * @returns {*|jQuery|boolean}
1109 */
1110 acfe.findClosestModal = function($el) {
1111
1112 // move up through each parent and try again
1113 for (var parent of $el.parents()) {
1114
1115 var $parent = $(parent);
1116 var $modal = $parent.find('>.acfe-modal');
1117
1118 if ($modal.length) {
1119 return $modal;
1120 }
1121
1122 }
1123
1124 return false;
1125
1126 };
1127
1128
1129 /**
1130 * acfe.getClosestModal
1131 *
1132 * @param $el
1133 * @param args
1134 * @returns {boolean|*|jQuery}
1135 */
1136 acfe.getClosestModal = function($el, args) {
1137 var $modal = acfe.findClosestModal($el);
1138
1139 if (!$modal.length) {
1140 return false;
1141 }
1142
1143 return this.getModal($modal, args);
1144 };
1145
1146
1147 /**
1148 * acfe.newModal
1149 *
1150 * @param $modal
1151 * @param args
1152 * @returns {*}
1153 */
1154 acfe.newModal = function($modal, args) {
1155
1156 // jquery object
1157 if (acfe.isJquery($modal)) {
1158
1159 var modal = $modal.data('acf');
1160 if (modal) {
1161 return modal.update(args);
1162 }
1163
1164 // instantiate
1165 modal = new acfe.Modal($modal, args);
1166
1167 // actions
1168 acf.doAction('acfe/new_modal', modal);
1169 acfe.doActionDeprecated('new_modal', [modal], '0.9.0.5', 'acfe/new_modal');
1170
1171 // return
1172 return modal;
1173
1174 }
1175
1176 // default
1177 args = acf.parseArgs($modal, {
1178 open: true
1179 });
1180
1181 // instantiate
1182 modal = new acfe.Modal(args);
1183
1184 // actions
1185 acf.doAction('acfe/new_modal', modal);
1186 acfe.doActionDeprecated('new_modal', [modal], '0.9.0.5', 'acfe/new_modal');
1187
1188 // return
1189 return modal;
1190
1191 }
1192
1193
1194 /**
1195 * acfe.Modal
1196 */
1197 acfe.Modal = acf.Model.extend({
1198
1199 data: {},
1200 modal: '', // modal id
1201 title: '',
1202 content: '',
1203 footer: '',
1204 class: '',
1205 size: 'medium',
1206 width: 0,
1207 open: false,
1208 destroy: false,
1209
1210 eventScope: '.acfe-modal',
1211
1212 onOpen: function() {},
1213 onClose: function() {},
1214
1215 setup: function($el, args) {
1216
1217 // default case: 2 arguments
1218 // acfe.newModal($el, {title: 'Hello World'})
1219
1220 // case: only one argument
1221 // acfe.newModal({title: 'Hello World'}) > create jquery element
1222 if (!acfe.isJquery($el)) {
1223 args = $el;
1224 $el = $('<div class="acfe-modal"></div>').appendTo('body'); // append modal to body
1225 }
1226
1227 // set $el
1228 // inherit: <div class="acfe-modal" data-title="Hello World" data-size="large"></div>
1229 this.$el = $el;
1230 $.extend(this, $el.data());
1231
1232 // cast args as object
1233 // inherit from args
1234 args = acfe.getObject(args);
1235 $.extend(this, args);
1236
1237 // render
1238 this.prepareRender();
1239 this.render();
1240
1241 },
1242
1243 update: function(args) {
1244
1245 // bail early
1246 if (typeof args === 'undefined') {
1247 return this;
1248 }
1249
1250 // cast as object
1251 args = acfe.getObject(args);
1252 $.extend(this, args);
1253
1254 // render
1255 this.render();
1256
1257 if (this.open) {
1258 this.show();
1259 }
1260
1261 // allow chaining
1262 return this;
1263
1264 },
1265
1266 initialize: function() {
1267
1268 // action
1269 acf.doAction(`acfe/modal/init`, this);
1270 acf.doAction(`acfe/modal/init/id=${this.modal}`, this);
1271
1272 if (this.open) {
1273 this.show();
1274 }
1275
1276 // add custom events
1277 this.addEvents({
1278 'click .close': 'onClickClose',
1279 });
1280
1281 },
1282
1283 on: function() {
1284
1285 acf.Model.prototype.on.apply(this, arguments);
1286
1287 // allow chaining
1288 return this;
1289
1290 },
1291
1292 $wrapper: function() {
1293 return this.$('> .acfe-modal-wrapper');
1294 },
1295
1296 $title: function(val) {
1297 return !acfe.isUndefined(val) ? this.$('> .acfe-modal-wrapper > .acfe-modal-title > .title').html(val) : this.$('> .acfe-modal-wrapper > .acfe-modal-title');
1298 },
1299
1300 $content: function(val) {
1301 return !acfe.isUndefined(val) ? this.$('> .acfe-modal-wrapper > .acfe-modal-content').html(val) : this.$('> .acfe-modal-wrapper > .acfe-modal-content');
1302 },
1303
1304 $footer: function(val) {
1305 return !acfe.isUndefined(val) ? this.$('> .acfe-modal-wrapper > .acfe-modal-footer').html(val) : this.$('> .acfe-modal-wrapper > .acfe-modal-footer');
1306 },
1307
1308 prepareRender: function() {
1309
1310 if (!this.$wrapper().length) {
1311 this.$el.wrapInner('<div class="acfe-modal-wrapper"></div>');
1312 }
1313
1314 if (!this.$content().length) {
1315 this.$wrapper().wrapInner('<div class="acfe-modal-content"></div>');
1316 }
1317
1318 },
1319
1320 render: function() {
1321
1322 // render content
1323 this.renderContent();
1324
1325 // clear class
1326 this.$el.removeClass('-medium -large -full');
1327
1328 if (this.size) {
1329 this.$el.addClass('-' + this.size);
1330 }
1331
1332 if (this.class) {
1333 this.$el.addClass(this.class);
1334 }
1335
1336 if (this.width) {
1337 this.$wrapper().css('max-width', this.width + 'px');
1338 }
1339
1340 // hide tinymce buttons dropdown when scrolling modal
1341 // fix position issues
1342 if (typeof tinymce !== 'undefined' && acf.isset(tinymce, 'ui', 'FloatPanel')) {
1343 this.$content().off('scroll.tinymcePanel').on('scroll.tinymcePanel', function(e) {
1344 tinymce.ui.FloatPanel.hideAll();
1345 });
1346 }
1347
1348 },
1349
1350 renderContent: function() {
1351
1352 // append title html
1353 if (!this.$title().length && this.title) {
1354 this.$wrapper().prepend('<div class="acfe-modal-title"><span class="title"></span><button class="close"></button></div>');
1355
1356 // remove title html
1357 } else if (this.title === false) {
1358 this.$title().remove();
1359 }
1360
1361 // append footer html
1362 if (!this.$footer().length && this.footer) {
1363 this.$wrapper().append('<div class="acfe-modal-footer"></div>');
1364
1365 // remove footer html
1366 } else if (this.footer === false) {
1367 this.$footer().remove();
1368 }
1369
1370 // title
1371 this.$title(acfe.isFunction(this.title) ? this.title.apply(this) : this.title);
1372
1373 // content
1374 if (this.content) {
1375 this.$content(acfe.isFunction(this.content) ? this.content.apply(this) : this.content);
1376 }
1377
1378 // footer
1379 if (this.footer) {
1380 this.$footer(acfe.isFunction(this.footer) ? this.footer.apply(this) : '<button class="button button-large button-primary close">' + this.footer + '</button>');
1381 }
1382
1383 },
1384
1385 show: function() {
1386
1387 // add class
1388 this.$el.addClass('-open');
1389
1390 // action
1391 acf.doAction(`acfe/modal/open`, this);
1392 acf.doAction(`acfe/modal/open/id=${this.modal}`, this);
1393
1394 // function
1395 this.onOpen.apply(this);
1396
1397 // event
1398 this.trigger('open');
1399
1400 // property
1401 this.open = true;
1402
1403 },
1404
1405 close: function() {
1406
1407 // remove style & class
1408 this.$el.removeAttr('style');
1409 this.$el.removeClass('-open');
1410
1411 // action
1412 acf.doAction(`acfe/modal/close`, this);
1413 acf.doAction(`acfe/modal/close/id=${this.modal}`, this);
1414
1415 // function
1416 this.onClose.apply(this);
1417
1418 // event
1419 this.trigger('close');
1420
1421 // property
1422 this.open = false;
1423
1424 // destroy
1425 if (this.destroy) {
1426 this.remove();
1427 }
1428
1429 },
1430
1431 onClickClose: function(e, $el) {
1432
1433 e.preventDefault();
1434 this.close();
1435
1436 }
1437
1438 });
1439
1440
1441 /**
1442 * acfe.closeModal
1443 *
1444 * @param $el
1445 * @returns {*}
1446 */
1447 acfe.closeModal = function($el) {
1448
1449 // last modal
1450 if (acfe.isUndefined($el)) {
1451 return modalManager.closeLastModal();
1452
1453 // jQuery element
1454 } else if (acfe.isJquery($el)) {
1455
1456 var modal = acfe.getModal($el);
1457 if (modal) {
1458 modal.close();
1459 }
1460
1461 }
1462
1463 };
1464
1465
1466 /**
1467 * modal manager
1468 *
1469 * @type {acf.Model}
1470 */
1471 var modalManager = new acf.Model({
1472
1473 actions: {
1474 'acfe/modal/open': 'onOpen',
1475 'acfe/modal/close': 'onClose',
1476 },
1477
1478 events: {
1479 'click .acfe-modal-overlay': 'onClick',
1480 'keyup': 'onKeyUp',
1481 },
1482
1483 getModals: function() {
1484
1485 return acfe.getModals({
1486 open: true,
1487 });
1488
1489 },
1490
1491 onOpen: function(modal) {
1492
1493 this.syncModals();
1494
1495 var $body = $('body');
1496
1497 if (!$body.hasClass('acfe-modal-opened')) {
1498 $body.addClass('acfe-modal-opened').append($('<div class="acfe-modal-overlay" />'));
1499 }
1500
1501 // show subfields
1502 acf.getFields({
1503 parent: modal.$el,
1504 visible: true,
1505 }).map(function(field) {
1506 acf.doAction('show_field', field, 'group');
1507 });
1508
1509 },
1510
1511 onClose: function(modal) {
1512
1513 this.syncModals();
1514
1515 if (!this.getModals().length) {
1516 $('.acfe-modal-overlay').remove();
1517 $('body').removeClass('acfe-modal-opened');
1518 }
1519
1520 },
1521
1522 onClick: function(e) {
1523
1524 e.preventDefault();
1525 this.closeLastModal();
1526
1527 },
1528
1529 onKeyUp: function(e) {
1530 if (e.keyCode === 27 && $('body').hasClass('acfe-modal-opened')) {
1531 e.preventDefault();
1532 this.closeLastModal();
1533 }
1534 },
1535
1536 closeLastModal: function() {
1537
1538 var modals = this.getModals();
1539
1540 if (modals.length) {
1541 modals[modals.length - 1].close();
1542 }
1543
1544 },
1545
1546 syncModals: function() {
1547
1548 // multiple popups: add css margin
1549 // add acfe-modal-sub to all modals, except the last one
1550 this.getModals().map(function(modal, i) {
1551
1552 // last modal
1553 if (i === this.getModals().length - 1) {
1554 return modal.$el.removeClass('acfe-modal-sub').css('margin-left', '');
1555 }
1556
1557 // other popups
1558 modal.$el.addClass('acfe-modal-sub').css('margin-left', -(500 / (i + 1)));
1559
1560 }, this);
1561
1562 }
1563
1564 });
1565
1566
1567 /**
1568 * link manager
1569 *
1570 * @type {acf.Model}
1571 */
1572 var linkManager = new acf.Model({
1573
1574 events: {
1575 'click a[data-modal]': 'onClick',
1576 'click button[data-modal]': 'onClick',
1577 'click input[data-modal]': 'onClick',
1578 },
1579
1580 onClick: function(e, $el) {
1581
1582 // prevent default
1583 e.preventDefault();
1584
1585 // vars
1586 var data = $el.data();
1587 var modal = data.modal ? acfe.getModal(data.modal) : acfe.getClosestModal($el);
1588
1589 if (modal) {
1590
1591 modal.update(data);
1592 modal.show();
1593
1594 }
1595
1596 },
1597
1598 });
1599
1600
1601 /**
1602 * acfe.Popup
1603 *
1604 * @deprecated
1605 */
1606 acfe.Popup = function($modal, args) {
1607
1608 // notice
1609 acfe.deprecatedFunction('acfe.Popup', '0.8.8.11', 'acfe.newModal');
1610
1611 // jquery object
1612 if (acfe.isJquery($modal)) {
1613
1614 // default
1615 args = acf.parseArgs(args, {
1616 open: true
1617 });
1618
1619 return acfe.newModal($modal, args);
1620
1621 }
1622
1623 // default
1624 args = acf.parseArgs($modal, {
1625 open: true
1626 });
1627
1628 return acfe.newModal(args);
1629
1630 }
1631
1632 })(jQuery);
1633 (function($) {
1634
1635 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
1636 return;
1637 }
1638
1639 /**
1640 * acf.Model.get
1641 *
1642 * Extends acf.Model.get to allow dot notation & default value
1643 *
1644 * @param name
1645 * @param def
1646 * @returns {*|null}
1647 */
1648 acf.Model.prototype.get = function(name = null, def = null) {
1649 return name === null ? this.data : acfe.arrayGet(this.data, name, def);
1650 };
1651
1652
1653 /**
1654 *
1655 * acf.Model.has
1656 *
1657 * Extends acf.Model.has to allow dot notation
1658 *
1659 * @param name
1660 * @returns {boolean}
1661 */
1662 acf.Model.prototype.has = function(name) {
1663 return acfe.arrayGet(this.data, name) !== null;
1664 };
1665
1666
1667 /**
1668 * acf.get
1669 *
1670 * Extends acf.get to allow dot notation & default value
1671 *
1672 * @param name
1673 * @param def
1674 * @returns {*|null}
1675 */
1676 acf.get = function(name = null, def = null) {
1677 return name === null ? this.data : acfe.arrayGet(this.data, name, def);
1678 };
1679
1680
1681 /**
1682 * acf.has
1683 *
1684 * Extends acf.has to allow dot notation
1685 *
1686 * @param name
1687 * @returns {boolean}
1688 */
1689 acf.has = function(name) {
1690 return acfe.arrayGet(this.data, name) !== null;
1691 };
1692
1693
1694 /**
1695 *
1696 * acf.set
1697 *
1698 * Extends acf.set to allow dot notation & default value
1699 *
1700 * @param name
1701 * @param value
1702 * @returns {acf}
1703 */
1704 acf.set = function(name, value) {
1705 acfe.arraySet(this.data, name, value);
1706 return this;
1707 };
1708
1709 })(jQuery);
1710 (function($) {
1711
1712 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
1713 return;
1714 }
1715
1716 /**
1717 * acf helpers
1718 *
1719 * acf.strReplace()
1720 * acf.strCamelCase()
1721 * acf.strPascalCase()
1722 * acf.strSlugify()
1723 * acf.strSanitize()
1724 * acf.strMatch()
1725 */
1726
1727
1728 /**
1729 * acfe.getString
1730 *
1731 * Parse value as string, also allows integer 0
1732 *
1733 * @param val
1734 * @returns {string|string}
1735 */
1736 acfe.getString = function(val) {
1737
1738 if (acfe.isObject(val)) {
1739 return JSON.stringify(val);
1740 }
1741
1742 return !acfe.isEmpty(val) ? '' + val : '';
1743 };
1744
1745
1746 /**
1747 * acfe.getTextNode
1748 *
1749 * @param $selector
1750 * @returns {*}
1751 */
1752 acfe.getTextNode = function($selector) {
1753
1754 if ($selector.exists()) {
1755 for (row of $selector.contents()) {
1756
1757 var text = $.trim($(row).text());
1758 if (text) {
1759 return text;
1760 }
1761
1762 }
1763 }
1764
1765 return '';
1766
1767 };
1768
1769
1770 /**
1771 *
1772 * @param string
1773 * @returns {string}
1774 */
1775 acfe.ucFirst = function(string) {
1776 return string.charAt(0).toUpperCase() + string.slice(1);
1777 };
1778
1779 })(jQuery);
1780 (function($) {
1781
1782 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
1783 return;
1784 }
1785
1786 /**
1787 * Tooltip
1788 *
1789 * A fixed version of acf-js-tooltip which allow multiple tooltips on different elements with onclick support
1790 */
1791 new acf.Model({
1792 tooltip: false,
1793 events: {
1794 'mouseenter .acfe-js-tooltip': 'showTitle',
1795 'mouseup .acfe-js-tooltip': 'hideTitle',
1796 'mouseleave .acfe-js-tooltip': 'hideTitle',
1797 'focus .acfe-js-tooltip': 'showTitle',
1798 'blur .acfe-js-tooltip': 'hideTitle',
1799 'keyup .acfe-js-tooltip': 'onKeyUp'
1800 },
1801 showTitle: function(e, $el) {
1802
1803 // vars
1804 var title = $el.attr('title');
1805
1806 // bail early if no title
1807 if (!title) {
1808 return;
1809 }
1810
1811 // clear title to avoid default browser tooltip
1812 $el.attr('title', '');
1813 $el.data('acfe-js-tooltip-title', title);
1814
1815 // esc html
1816 title = acf.escHtml(title);
1817
1818 // create
1819 if (!this.tooltip) {
1820
1821 this.tooltip = acf.newTooltip({
1822 text: title,
1823 target: $el
1824 });
1825
1826 // update
1827 } else {
1828
1829 this.tooltip.update({
1830 text: title,
1831 target: $el
1832 });
1833
1834 }
1835 },
1836 hideTitle: function(e, $el) {
1837
1838 // hide tooltip
1839 this.tooltip.hide();
1840
1841 // restore title
1842 $el.attr('title', $el.data('acfe-js-tooltip-title'));
1843
1844 },
1845 onKeyUp: function(e, $el) {
1846 if (e.key === 'Escape') {
1847 this.hideTitle(e, $el);
1848 }
1849 }
1850 });
1851
1852
1853 /**
1854 * Field Tooltip
1855 *
1856 * Toggleable tooltip for fields
1857 */
1858 var fieldTooltip = new acf.Model({
1859
1860 tooltips: {},
1861
1862 events: {
1863 'click .acfe-field-tooltip': 'clickTooltip',
1864 },
1865
1866 clickTooltip: function(e, $el) {
1867
1868 // title
1869 var title = $el.attr('title');
1870 if (!title) {
1871 return;
1872 }
1873
1874 // get field
1875 var field = acf.getClosestField($el);
1876 if (!field) {
1877 return;
1878 }
1879
1880 this.toggle(field, $el, title);
1881
1882 },
1883
1884 toggle: function(field, $el, title) {
1885
1886 // clear title to avoid default browser tooltip
1887 $el.attr('title', '');
1888
1889 // open
1890 if (!this.tooltips[field.cid]) {
1891 this.open(field, $el, title);
1892
1893 // close
1894 } else {
1895 this.close(field, $el, title);
1896 }
1897
1898 },
1899
1900 open: function(field, $el, title) {
1901
1902 this.tooltips[field.cid] = acf.newTooltip({
1903 text: title,
1904 target: $el
1905 });
1906
1907 if (acfe.isWP('5.5')) {
1908 $el.removeClass('dashicons-info-outline').addClass('dashicons-remove');
1909 }
1910
1911 },
1912
1913 close: function(field, $el, title) {
1914
1915 // hide tooltip
1916 this.tooltips[field.cid].hide();
1917
1918 // restore title
1919 $el.attr('title', this.tooltips[field.cid].get('text'));
1920
1921 this.tooltips[field.cid] = false;
1922
1923 if (acfe.isWP('5.5')) {
1924 $el.removeClass('dashicons-remove').addClass('dashicons-info-outline');
1925 }
1926
1927 }
1928
1929 });
1930
1931 new acf.Model({
1932 actions: {
1933 'hide_field': 'onHideField',
1934 },
1935 onHideField: function(field) {
1936 if (fieldTooltip.tooltips[field.cid]) {
1937 fieldTooltip.close(field, field.$el.find('.acfe-field-tooltip:first'));
1938 }
1939 }
1940 })
1941
1942 })(jQuery);
1943 (function($) {
1944
1945 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
1946 return;
1947 }
1948
1949 /**
1950 * acfe.isArray
1951 *
1952 * Copy acf.isArray
1953 *
1954 * @param a
1955 * @returns {*}
1956 */
1957 acfe.isArray = function(a) {
1958 return Array.isArray(a);
1959 }
1960
1961
1962 /**
1963 * acfe.isObject
1964 *
1965 * Copy acf.isObject enhanced
1966 *
1967 * @param a
1968 * @returns {*}
1969 */
1970 acfe.isObject = function(a) {
1971 return typeof a === 'object' && !acfe.isArray(a);
1972 }
1973
1974
1975 /**
1976 * acfe.isNumeric
1977 *
1978 * Copy acf.isNumeric
1979 *
1980 * @param a
1981 * @returns {*}
1982 */
1983 acfe.isNumeric = function(a) {
1984 return !isNaN(parseFloat(a)) && isFinite(a);
1985 }
1986
1987
1988 /**
1989 * acfe.isString
1990 *
1991 * @param a
1992 * @returns {boolean}
1993 */
1994 acfe.isString = function(a) {
1995 return typeof a === 'string';
1996 }
1997
1998
1999 /**
2000 * acfe.isUndefined
2001 *
2002 * @param a
2003 * @returns {boolean}
2004 */
2005 acfe.isUndefined = function(a) {
2006 return typeof a === 'undefined';
2007 }
2008
2009
2010 /**
2011 * acfe.isFunction
2012 *
2013 * @param a
2014 * @returns {boolean}
2015 */
2016 acfe.isFunction = function(a) {
2017 return typeof a === 'function';
2018 }
2019
2020
2021 /**
2022 * acfe.isBool
2023 *
2024 * @param a
2025 * @returns {boolean}
2026 */
2027 acfe.isBool = function(a) {
2028 return typeof a === 'boolean';
2029 }
2030
2031
2032 /**
2033 * acfe.isInt
2034 *
2035 * @param a
2036 * @returns {boolean}
2037 */
2038 acfe.isInt = function(a) {
2039 return Number.isInteger(a);
2040 }
2041
2042
2043 /**
2044 * acfe.isJquery
2045 *
2046 * @param $a
2047 * @returns {boolean}
2048 */
2049 acfe.isJquery = function($a) {
2050 return $a instanceof jQuery
2051 }
2052
2053
2054 /**
2055 * acfe.isEmpty
2056 *
2057 * Allows integer 0 to be used
2058 *
2059 * @param val
2060 * @returns {boolean}
2061 */
2062 acfe.isEmpty = function(val) {
2063
2064 // array
2065 if (acfe.isArray(val)) {
2066 return !val.length;
2067
2068 // object
2069 } else if (acfe.isObject(val)) {
2070 return val && Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype
2071
2072 // string
2073 } else if (acfe.isString(val)) {
2074 return !val.length;
2075
2076 }
2077
2078 // integer 0
2079 return !val && !acfe.isNumeric(val);
2080
2081 };
2082
2083 })(jQuery);
2084 (function($) {
2085
2086 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
2087 return;
2088 }
2089
2090 /**
2091 * acfe.slugify
2092 *
2093 * @param str
2094 * @returns {string}
2095 */
2096 acfe.slugify = function(str) {
2097 return str.replace(/[\s\./]+/g, '-').replace(/[^\p{L}\p{N}_-]+/gu, '').replace(/-+$/, '').toLowerCase();
2098 }
2099
2100 /**
2101 * acfe.addQueryArgs
2102 *
2103 * @returns {string|any|string}
2104 */
2105 acfe.addQueryArgs = function() {
2106
2107 let url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
2108 let args = arguments.length > 1 ? arguments[1] : undefined;
2109
2110 // If no arguments are to be appended, return original URL.
2111 if (!args || !Object.keys(args).length) {
2112 return url;
2113 }
2114
2115 let baseUrl = url; // Determine whether URL already had query arguments.
2116
2117 const queryStringIndex = url.indexOf('?');
2118
2119 if (queryStringIndex !== -1) {
2120 // Merge into existing query arguments.
2121 args = Object.assign(acfe.getQueryArgs(url), args); // Change working base URL to omit previous query arguments.
2122
2123 baseUrl = baseUrl.substr(0, queryStringIndex);
2124 }
2125
2126 return baseUrl + '?' + buildQueryString(args);
2127
2128 };
2129
2130
2131 /**
2132 * acfe.getQueryArgs
2133 *
2134 * @param url
2135 * @returns {string}
2136 */
2137 acfe.getQueryArgs = function(url) {
2138
2139 return (getQueryString(url) || '' // Normalize space encoding, accounting for PHP URL encoding
2140 // corresponding to `application/x-www-form-urlencoded`.
2141 //
2142 // See: https://tools.ietf.org/html/rfc1866#section-8.2.1
2143 ).replace(/\+/g, '%20').split('&').reduce((accumulator, keyValue) => {
2144 const [key, value = ''] = keyValue.split('=') // Filtering avoids decoding as `undefined` for value, where
2145 // default is restored in destructuring assignment.
2146 .filter(Boolean).map(decodeURIComponent);
2147
2148 if (key) {
2149 const segments = key.replace(/\]/g, '').split('[');
2150 setPath(accumulator, segments, value);
2151 }
2152
2153 return accumulator;
2154 }, Object.create(null));
2155
2156 };
2157
2158
2159 /**
2160 * acfe.getFragment
2161 *
2162 * getFragment('http://localhost:8080/this/is/a/test?query=true#fragment'); // '#fragment'
2163 * getFragment('https://wordpress.org#another-fragment?query=true'); // '#another-fragment'
2164 *
2165 * @param url
2166 * @returns {string}
2167 */
2168 acfe.getFragment = function(url) {
2169
2170 const matches = /^\S+?(#[^\s\?]*)/.exec(url);
2171
2172 if (matches) {
2173 return matches[1];
2174 }
2175
2176 return '';
2177
2178 };
2179
2180
2181 /**
2182 * acfe.getCurrentUrl
2183 *
2184 * @returns {*}
2185 */
2186 acfe.getCurrentUrl = function() {
2187 return self.location.href;
2188 };
2189
2190
2191 /**
2192 * acfe.getCurrentPath
2193 *
2194 * @returns {string|string|string|*}
2195 */
2196 acfe.getCurrentPath = function() {
2197 return self.location.pathname;
2198 };
2199
2200
2201 /**
2202 * acfe.getCurrentFilename
2203 *
2204 * @returns {string}
2205 */
2206 acfe.getCurrentFilename = function() {
2207 return acfe.getFilename(acfe.getCurrentPath());
2208 };
2209
2210
2211 /**
2212 * acfe.getFilename
2213 *
2214 * @param path
2215 * @returns {*}
2216 */
2217 acfe.getFilename = function(path) {
2218 return path.split('/').pop();
2219 };
2220
2221
2222 /**
2223 * buildQueryString
2224 *
2225 * wp-includes/js/dist/url.js
2226 *
2227 * @param data
2228 * @returns {string}
2229 */
2230 var buildQueryString = function(data) {
2231
2232 let string = '';
2233 const stack = Object.entries(data);
2234 let pair;
2235
2236 while (pair = stack.shift()) {
2237 let [key, value] = pair; // Support building deeply nested data, from array or object values.
2238
2239 const hasNestedData = Array.isArray(value) || value && value.constructor === Object;
2240
2241 if (hasNestedData) {
2242 // Push array or object values onto the stack as composed of their
2243 // original key and nested index or key, retaining order by a
2244 // combination of Array#reverse and Array#unshift onto the stack.
2245 const valuePairs = Object.entries(value).reverse();
2246
2247 for (const [member, memberValue] of valuePairs) {
2248 stack.unshift([`${key}[${member}]`, memberValue]);
2249 }
2250 } else if (value !== undefined) {
2251 // Null is treated as special case, equivalent to empty string.
2252 if (value === null) {
2253 value = '';
2254 }
2255
2256 string += '&' + [key, value].map(encodeURIComponent).join('=');
2257 }
2258 } // Loop will concatenate with leading `&`, but it's only expected for all
2259 // but the first query parameter. This strips the leading `&`, while still
2260 // accounting for the case that the string may in-fact be empty.
2261
2262
2263 return string.substr(1);
2264
2265 };
2266
2267
2268 /**
2269 * getQueryString
2270 *
2271 * wp-includes/js/dist/url.js
2272 *
2273 * @param url
2274 * @returns {string}
2275 */
2276 var getQueryString = function(url) {
2277 let query;
2278
2279 try {
2280 query = new URL(url, 'http://example.com').search.substring(1);
2281 } catch (error) {}
2282
2283 if (query) {
2284 return query;
2285 }
2286 };
2287
2288
2289 /**
2290 * setPath
2291 *
2292 * wp-includes/js/dist/url.js
2293 *
2294 * @param object
2295 * @param path
2296 * @param value
2297 */
2298 var setPath = function(object, path, value) {
2299
2300 const length = path.length;
2301 const lastIndex = length - 1;
2302
2303 for (let i = 0; i < length; i++) {
2304 let key = path[i];
2305
2306 if (!key && Array.isArray(object)) {
2307 // If key is empty string and next value is array, derive key from
2308 // the current length of the array.
2309 key = object.length.toString();
2310 }
2311
2312 key = ['__proto__', 'constructor', 'prototype'].includes(key) ? key.toUpperCase() : key; // If the next key in the path is numeric (or empty string), it will be
2313 // created as an array. Otherwise, it will be created as an object.
2314
2315 const isNextKeyArrayIndex = !isNaN(Number(path[i + 1]));
2316 object[key] = i === lastIndex ? // If at end of path, assign the intended value.
2317 value : // Otherwise, advance to the next object in the path, creating
2318 // it if it does not yet exist.
2319 object[key] || (isNextKeyArrayIndex ? [] : {});
2320
2321 if (Array.isArray(object[key]) && !isNextKeyArrayIndex) {
2322 // If we current key is non-numeric, but the next value is an
2323 // array, coerce the value to an object.
2324 object[key] = {
2325 ...object[key]
2326 };
2327 } // Update working reference object to the next in the path.
2328
2329
2330 object = object[key];
2331 }
2332
2333 };
2334
2335 })(jQuery);
2336 (function($) {
2337
2338 if (typeof acf === 'undefined' || typeof acfe === 'undefined') {
2339 return;
2340 }
2341
2342
2343 /**
2344 * acfe.copyClipboard
2345 *
2346 * @param data
2347 * @param message
2348 * @param callback
2349 */
2350 acfe.copyClipboard = function(data, message, callback) {
2351 new copyClipboard(data, message, callback);
2352 }
2353
2354
2355 /**
2356 * copyClipboard
2357 *
2358 * message = {
2359 * auto: {
2360 * title: acf.__('Layout copied to clipboard'),
2361 * text: acf.__('You can now paste it anywhere using the "Paste Layout" secondary action.'),
2362 * },
2363 * manual: {
2364 * title: acf.__('Layout ready to be copied'),
2365 * text: acf.__('Please copy the following data to your clipboard.') + "<br /><br />" + acf.__('You can then paste it anywhere using the "Paste Layout" secondary action.'),
2366 * },
2367 * }
2368 */
2369 var copyClipboard = acf.Model.extend({
2370
2371 data: null,
2372 message: {
2373 auto: {
2374 title: acf.__('Content copied clipboard'),
2375 text: '',
2376 },
2377 manual: {
2378 title: acf.__('Content ready to be copied'),
2379 text: acf.__('Please copy the following data to your clipboard:')
2380 },
2381 },
2382 callback: acfe.newModal,
2383
2384 setup: function(data, message, callback) {
2385
2386 this.data = data;
2387
2388 if (message) {
2389 this.message = message;
2390 }
2391
2392 if (callback) {
2393 this.callback = callback;
2394 }
2395
2396 },
2397
2398 initialize: function() {
2399
2400 var args = {
2401 title: this.message.auto.title,
2402 destroy: true,
2403 width: 400,
2404 text: this.message.auto.text,
2405 class: 'acfe-modal-fc-copy-layout',
2406 input: false,
2407 events: {
2408 'click textarea': 'onClickTextarea',
2409 'click .copy': 'onClickCopy',
2410 },
2411 content: function() {
2412
2413 if (!this.input && !this.text) {
2414 return;
2415 }
2416
2417 var html = '';
2418
2419 html += `<div class="acfe-modal-spacer">`;
2420 html += `<div>${this.text}</div>`;
2421
2422 if (this.input) {
2423 html += `<textarea readonly></textarea>`;
2424 }
2425
2426 html += `</div>`;
2427
2428 return html;
2429
2430 },
2431 footer: function() {
2432
2433 if (this.input) {
2434 return `<a href="#" class="button button-large close">${acf.__('Cancel')}</a> <a href="#" class="button button-large button-primary copy">${acf.__('Copy and close')}</a>`;
2435 }
2436
2437 return `<a href="#" class="button button-large button-primary close">${acf.__('Close')}</a>`;
2438 },
2439 onOpen: function() {
2440 if (this.input) {
2441 var $textarea = this.$el.find('textarea');
2442 $textarea.val(this.input);
2443 $textarea.select();
2444 }
2445 },
2446 onClickTextarea: function(e, $el) {
2447 $el.select();
2448 },
2449 onClickCopy: function(e, $el) {
2450
2451 e.preventDefault();
2452
2453 var $textarea = this.$el.find('textarea');
2454 $textarea.select();
2455 document.execCommand("copy");
2456 this.close();
2457
2458 },
2459 };
2460
2461
2462 this.tryCopy().then(this.proxy(function(success) {
2463 if (success) {
2464
2465 // use callback
2466 if (this.callback) {
2467 this.callback(args);
2468 }
2469
2470 } else {
2471 args.title = this.message.manual.title;
2472 args.text = this.message.manual.text;
2473 args.input = this.data;
2474 acfe.newModal(args);
2475 }
2476 }));
2477
2478 },
2479
2480 tryCopy: function() {
2481
2482 var data = this.data;
2483 var tryFallback = this.proxy(this.tryFallback);
2484
2485 return new Promise(function(resolve) {
2486 if (navigator.clipboard && navigator.clipboard.writeText) {
2487 navigator.clipboard.writeText(data).then(function() {
2488 resolve(true);
2489 }).catch(function() {
2490 resolve(tryFallback());
2491 });
2492 } else {
2493 resolve(tryFallback());
2494 }
2495 });
2496 },
2497
2498 tryFallback: function() {
2499
2500 var $textarea = $('<textarea style="position:absolute;left:-9999px;top:0;" />').appendTo('body');
2501 $textarea.val(this.data).select();
2502
2503 var success = false;
2504 try {
2505 success = document.execCommand('copy');
2506 } catch (e) {}
2507
2508 $textarea.remove();
2509 return success;
2510 },
2511
2512
2513 });
2514
2515
2516 /**
2517 * acfe.scrollTo
2518 *
2519 * Scroll to element, if needed with acf.isInView()
2520 *
2521 * @param $el
2522 * @param scrollTime
2523 * @constructor
2524 */
2525 acfe.scrollTo = function($el, scrollTime = 500) {
2526
2527 if (!acf.isInView($el)) {
2528 $('body, html').animate({
2529 scrollTop: $el.offset().top - $(window).height() / 2
2530 }, scrollTime);
2531 }
2532
2533 }
2534
2535
2536 /**
2537 * acfe.versionCompare
2538 *
2539 * https://locutus.io/php/info/version_compare/
2540 *
2541 * @param v1
2542 * @param operator
2543 * @param v2
2544 * @returns {null|boolean|number}
2545 */
2546 acfe.versionCompare = function(v1, operator, v2) {
2547 let i
2548 let x
2549 let compare = 0
2550
2551 const vm = {
2552 dev: -6,
2553 alpha: -5,
2554 a: -5,
2555 beta: -4,
2556 b: -4,
2557 RC: -3,
2558 rc: -3,
2559 '#': -2,
2560 p: 1,
2561 pl: 1
2562 }
2563
2564 const _prepVersion = function(v) {
2565 v = ('' + v).replace(/[_\-+]/g, '.')
2566 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.')
2567 return (!v.length ? [-8] : v.split('.'))
2568 }
2569
2570 const _numVersion = function(v) {
2571 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10))
2572 }
2573 v1 = _prepVersion(v1)
2574 v2 = _prepVersion(v2)
2575 x = Math.max(v1.length, v2.length)
2576 for (i = 0; i < x; i++) {
2577 if (v1[i] === v2[i]) {
2578 continue
2579 }
2580 v1[i] = _numVersion(v1[i])
2581 v2[i] = _numVersion(v2[i])
2582 if (v1[i] < v2[i]) {
2583 compare = -1
2584 break
2585 } else if (v1[i] > v2[i]) {
2586 compare = 1
2587 break
2588 }
2589 }
2590 if (!operator) {
2591 return compare
2592 }
2593
2594 switch (operator) {
2595 case '>':
2596 case 'gt':
2597 return (compare > 0)
2598 case '>=':
2599 case 'ge':
2600 return (compare >= 0)
2601 case '<=':
2602 case 'le':
2603 return (compare <= 0)
2604 case '===':
2605 case '=':
2606 case 'eq':
2607 return (compare === 0)
2608 case '<>':
2609 case '!==':
2610 case 'ne':
2611 return (compare !== 0)
2612 case '':
2613 case '<':
2614 case 'lt':
2615 return (compare < 0)
2616 default:
2617 return null
2618 }
2619
2620 };
2621
2622 })(jQuery);