PageSourceSearch

https://papuanewguinea.travel/wp-content/themes/png/modules/ff-ajax/js/ff-ajax-v2.js?ver=1.0

js papuanewguinea.travel collected 2026-10-02 04:03:28 UTC 18,427 bytes, 631 lines download raw bytes

1// console.log( 'FF Ajax V2 ');
2
3function FF_Ajax_2(options){
4
5    if( !options.container ) return;
6    var _ = this;
7    
8    _.options = options;
9    
10    _.set_option('action', 'ff_ajax_query');
11    _.set_option('type', 'default');
12
13    _.container = options.container;
14    _.listings_con = _.container.querySelector('.ajax-loop');
15
16    _.original_query_args = { ...options.query_args }; // copy original args for restoration later
17
18    _.filters = {
19        meta_query: {},
20        tax_query: {},
21    };
22
23    _.ajax_request = null;
24
25    // filter indicators
26    _.filter_indicators_con = null;
27    if( typeof options.filter_indicators !== 'undefined' ) {
28        _.filter_indicators_con = _.container.querySelector(options.filter_indicators);
29        _.filter_indicators = {};
30    }
31
32    _.load_more_init();
33    _.filter_fields_init();
34
35    _.container.classList.add('ff_ajax_init');
36    
37    console.log(_);
38}
39
40FF_Ajax_2.prototype.set_option = function(property, defaut_value){
41    if( typeof this.options[property] !== 'undefined' ) {
42        this[property] =this.options[property];
43    }
44    else {
45        this[property] = defaut_value;
46    }
47}
48
49FF_Ajax_2.prototype.filter_fields_init = function(){
50    var _ = this;
51    _.container.querySelectorAll('.ajax_filter').forEach(field=>{
52        if( field.nodeName == 'SELECT' ) {
53            _.filter_field_dropdown(field);
54        }
55        else if( field.classList.contains('toggle_field') ) {
56            _.filter_field_toggle(field);
57        }
58        else if( field.classList.contains('date') ) {
59            _.filter_field_date(field);
60        }
61    })
62}
63
64FF_Ajax_2.prototype.filter_field_dropdown = function(field){
65    var _ = this;
66    field.addEventListener('change', ()=>{
67
68        var type = field.dataset.type;
69        var key = ( type == 'tax_query' ) ? field.dataset.taxonomy : field.dataset.metaKey;
70
71        // var filter_indicator_label = field.value;
72        // if ( typeof field.dataset.indicatorSuffix !== 'undefined' ) {
73        //     filter_indicator_label = field.value +' '+ field.dataset.indicatorSuffix;
74        // }
75
76        var value = field.value;
77        var value_label = field.selectedOptions[0].text;
78
79        var filter_key = field.dataset.filterKey;
80        
81        _.update_filter_query( type, key, value, filter_key );
82
83        _.add_filter_indicator( type, key, value, value_label );
84
85        field.value = ''; // reset field back to blank
86
87        _.apply_filters();
88    })
89}
90
91FF_Ajax_2.prototype.filter_field_toggle = function(field){
92    var _ = this;
93    // console.log('filter_field_toggle', field);
94    var toggle = field.querySelector('.toggle');
95    var type = field.dataset.type;
96    var key = ( type == 'tax_query' ) ? field.dataset.taxonomy : field.dataset.metaKey;
97
98    toggle.addEventListener('click',()=>{
99
100        if( field.classList.contains('selected') ) {
101            // un-select
102            _.remove_filter_query(type, key);
103        }
104        else {
105            // select
106            _.update_filter_query(type, key, 1);
107        }
108
109        field.classList.toggle('selected');
110
111        _.apply_filters();
112
113    });
114}
115
116FF_Ajax_2.prototype.filter_field_date = function(field){
117    var _ = this;
118
119    var filter_key = field.dataset.metaKey;
120    var compare = field.dataset.compare;
121    
122    var field_con = field.parentElement;
123    var label = field_con.querySelector('.l');
124
125    var clear = null;
126
127    var dp = jQuery(field).datepicker({
128        onSelect: function(dateText, instance){
129            console.log('on select');
130            label.textContent = field.value;
131
132            var value = _.date_query_format(field.value);
133            _.filters[filter_key] = value;
134
135            if( !clear ) {
136                // clear button
137                clear = document.createElement('div');
138                clear.classList.add('clear');
139                clear.addEventListener('click',()=>{
140                    clear.remove();
141                    delete _.filters[filter_key];
142                    clear = null;
143                    label.textContent = label.dataset.label;
144                    field.value = '';
145
146                    // _.update_filter_query_date(filter_key, '', compare);
147
148                    _.update_filter_query( 'meta_query', filter_key, '' );
149
150                    _.apply_filters();
151
152                    // remove date field limits
153                    set_date_field_min_max(filter_key, null);
154                })
155                field_con.append(clear);
156            }   
157
158            _.update_filter_query( 'meta_query', filter_key, value, filter_key, compare);
159            // _.update_filter_query_date(filter_key, value, compare);
160            _.apply_filters();
161
162            // set date field limits
163            set_date_field_min_max(filter_key, field.value);  
164
165        }
166    });
167
168    if( field.classList.contains('date_from') ) {
169        _.date_from_field = dp;
170    }
171
172    if( field.classList.contains('date_to') ) {
173        _.date_to_field = dp;
174    }
175
176    if( typeof _.options.min_date !== 'undefined' ) {
177
178        if( typeof _.date_from_field !== 'undefined' ) {
179            _.date_from_field.datepicker( "option", "minDate", _.options.min_date );
180        }
181        if( typeof _.date_to_field !== 'undefined' ) {
182            _.date_to_field.datepicker( "option", "minDate", _.options.min_date );
183        }
184
185        // fix for datepicker showing on the bottom of the page after setting an option
186        var temp = document.getElementById('ui-datepicker-div');
187        if( temp ) {
188            temp.style.display = 'none';
189        }
190    }
191    
192    function set_date_field_min_max(filter_key, value){
193        if( filter_key == 'start_date' && typeof _.date_to_field !== 'undefined' ) {
194            _.date_to_field.datepicker( "option", "minDate", value );
195        }
196        if( filter_key == 'end_date' && typeof _.date_from_field !== 'undefined' ) {
197            _.date_from_field.datepicker( "option", "maxDate", value );
198        }
199    }
200}
201
202// FF_Ajax_2.prototype.filter_field_date2 = function(field){
203//     var _ = this;
204
205//     var filter_key = field.dataset.metaKey;
206//     var compare = field.dataset.compare;
207    
208//     var field_con = field.parentElement;
209//     var label = field_con.querySelector('.l');
210
211//     var clear = null;
212
213//     var dp = jQuery(field).datepicker({
214//         onSelect: function(dateText, instance){
215
216//             label.textContent = field.value;
217
218//             var value = _.date_query_format(field.value);
219//             _.filters[filter_key] = value;
220
221//             if( !clear ) {
222//                 // clear button
223//                 clear = document.createElement('div');
224//                 clear.classList.add('clear');
225//                 clear.addEventListener('click',()=>{
226//                     clear.remove();
227//                     delete _.filters[filter_key];
228//                     clear = null;
229//                     label.textContent = label.dataset.label;
230//                     field.value = '';
231
232//                     // _.update_filter_query_date(filter_key, '', compare);
233
234//                     _.update_filter_query( 'meta_query', filter_key, '' );
235
236//                     _.apply_filters();
237
238//                     // remove date field limits
239//                     set_date_field_min_max(filter_key, null);
240//                 })
241//                 field_con.append(clear);
242//             }   
243
244//             _.update_filter_query( 'meta_query', filter_key, value, filter_key, compare);
245//             // _.update_filter_query_date(filter_key, value, compare);
246//             _.apply_filters();
247
248//             // set date field limits
249//             set_date_field_min_max(filter_key, field.value);  
250//         }
251//     });
252
253//     if( field.classList.contains('date_from') ) {
254//         _.date_from_field = dp;
255
256//         if( typeof _.options.min_date !== 'undefined' ) {
257//             _.date_from_field.datepicker( "option", "minDate", _.options.min_date );
258//         }
259//     }
260
261//     if( field.classList.contains('date_to') ) {
262//         _.date_to_field = dp;
263//     }
264    
265//     function set_date_field_min_max(filter_key, value){
266//         if( filter_key == 'start_date' && typeof _.date_to_field !== 'undefined' ) {
267//             _.date_to_field.datepicker( "option", "minDate", value );
268//         }
269//         if( filter_key == 'end_date' && typeof _.date_from_field !== 'undefined' ) {
270//             _.date_from_field.datepicker( "option", "maxDate", value );
271//         }
272//     }
273    
274// }
275
276FF_Ajax_2.prototype.update_filter_query = function( type, key, value, filter_key = '', compare = '', compare_type = '' ){
277    
278    var _ = this;
279
280    if( type == 'post_type' ) {
281        _.options.query_args.post_type = ( value) ? value : _.original_query_args.post_type;
282        return;
283    }
284    
285    if( typeof _.options.query_args[type] === 'undefined' ) {
286        _.options.query_args[type] = [];
287    }
288
289    if( !filter_key ) {
290        filter_key = key;
291    }
292    
293    // console.log('update_filter_query', { type, key, value, filter_key })
294
295    _.filters[type][key] = value;
296
297    // var type_key_name = 'taxonomy';
298    var type_value_name = 'terms';
299
300    if( type == 'meta_query' ) {
301        // type_key_name = 'key';
302        type_value_name = 'value';
303    }
304    
305    // All - reset
306    if( value == 'all' || !value ) {
307        for( var i = 0; i < _.options.query_args[type].length; i++ ) {
308            // if( _.options.query_args[type][i][type_key_name] == key ) {
309            if( _.options.query_args[type][i].filter_key == filter_key ) {
310                _.options.query_args[type].splice(i, 1);
311                return;
312            }
313        }
314        return;
315    }
316
317    // check if term clause is present
318    var found = false;
319    for( var i = 0; i < _.options.query_args[type].length; i++ ) {
320        // if( _.options.query_args[type][i][type_key_name] == key ) {
321        if( _.options.query_args[type][i].filter_key == filter_key ) {
322            _.options.query_args[type][i][type_value_name] = value;
323            found = true;
324            break;
325        }
326    }
327
328    // clause not found, create new
329    if( !found ) {
330
331        var clause = {
332            taxonomy: key,
333            field: 'slug',
334            terms: value,
335        };
336
337        if( type == 'meta_query' ) {
338            clause = {
339                key: key,
340                value: value,
341                compare: compare ? compare : '=',
342            };
343
344            if( compare_type ) {
345                clause.type = compare_type;
346            }
347        }
348
349        clause.filter_key = filter_key;
350
351        // console.log({
352        //     type,
353        //     clause,
354        //     query_args: _.options.query_args,
355        // })
356
357        _.options.query_args[type].push(clause);
358    }
359
360    // console.log( 'update_filter_query', _.options.query_args );
361}
362
363FF_Ajax_2.prototype.update_filter_query_date = function(key, value, compare){
364    
365    var _ = this;
366
367    var query_type = 'meta_query';
368    
369    if( typeof _.options.query_args[query_type] === 'undefined' ) {
370        _.options.query_args[query_type] = [];
371    }
372
373    console.log('update_filter_query_date', {query_type, key, value, compare, args: _.options.query_args[query_type]});
374
375    // var type_key_name = 'key';
376    var type_value_name = 'value';
377
378    var found = false;
379
380    for( var i = 0; i < _.options.query_args[query_type].length; i++ ) {
381        var clause = _.options.query_args[query_type][i];
382
383        if( clause.key == key && clause.compare == compare ) {
384            // remove
385            if( !value ) {
386                _.options.query_args[query_type].splice(i, 1);
387                return;
388            }
389
390            // update
391            _.options.query_args[query_type][i][type_value_name] = value;
392            found = true;
393            break;
394        }
395    }
396
397    // clause not found, create new
398    if( !found ) {
399        _.options.query_args[query_type].push({
400            key,
401            value,
402            compare,
403            type: 'DATE',
404        });
405    }
406
407    // console.log( _.options.query_args[query_type] );
408}
409
410FF_Ajax_2.prototype.remove_filter_query = function(type, key){
411    var _ = this;
412
413    if( type == 'post_type' ) {
414        _.options.query_args.post_type = _.original_query_args.post_type;
415        return;
416    }
417
418    // var type_key_name = 'taxonomy';
419    // if( type == 'meta_query' ) {
420    //     type_key_name = 'key';
421    // }
422
423    for( var i = 0; i < _.options.query_args[type].length; i++ ) {
424        // if( _.options.query_args[type][i][type_key_name] == key ) {
425        if( _.options.query_args[type][i].filter_key == key ) {
426            _.options.query_args[type].splice(i, 1);
427            return;
428        }
429    }
430}
431
432FF_Ajax_2.prototype.query = function(callback){
433
434    var _ = this;
435
436    _.container.classList.add('ajax_loading')
437
438    if( _.ajax_request && typeof _.ajax_request.abort !== 'undefined' ) {
439        _.ajax_request.abort(); // abort previous request
440    }
441
442    var data = {
443        action: _.action,
444        type: _.type,
445        filters: _.filters,
446        query_args: _.options.query_args,
447        page: _.page,
448    }
449
450    // console.log('query', data);
451    
452    _.ajax_request = jQuery.ajax({
453        url: site_data.ajax_url,
454        type: "post",
455        data: data,
456        dataType : "json",
457    }).done(function(res){
458        
459        console.log('query result', res );
460
461        if( !res.result ) {
462            jQuery(_.listings_con).html(_.options.no_results_html);
463            _.load_more_con.classList.add('hide');
464        }
465        else {
466            
467            var html_items = jQuery(res.html);
468
469            if( _.page != 1 ) {
470                // append, used for load more
471                jQuery(_.listings_con).append(html_items);
472            } else {
473                // replace content
474                jQuery(_.listings_con).html(html_items);
475            }
476
477            _.check_have_more_posts(res);
478
479            jQuery('body').trigger('ff_ajax_after_query', [ _, html_items ]);
480
481        }
482
483        if( typeof callback === 'function' ) callback(res);
484
485        _.container.classList.remove('ajax_loading')
486    });
487
488}
489
490FF_Ajax_2.prototype.apply_filters = function(){
491    var _ = this;
492    _.page = 1;
493    console.log('apply_filters', _.filters, _.options.query_args );
494    _.query();
495}
496
497FF_Ajax_2.prototype.add_filter_indicator = function( type, key, value, label ){
498
499    // console.log('add_filter_indicator', { key, value, type })
500    var _ = this;
501
502    if( !_.filter_indicators_con ) return;
503
504    // console.log( 'add_filter_indicator', { key, value } )
505    if( typeof _.filter_indicators[key] === 'undefined' ) {
506        // add new
507        _.create_filter_indicator_item( type, key, value, label );
508        
509    } else {
510        // update existing
511        _.update_filter_indicator_item( type, key, value, label );
512    }
513}
514
515FF_Ajax_2.prototype.create_filter_indicator_item = function( type, key, value, label ){
516    var _ = this;
517
518    // create element
519    var el = document.createElement('div');
520    el.classList.add('filter_indicator');
521    
522    // text
523    var text = document.createElement('div');
524    text.classList.add('text');
525
526    if( !label ) label = value;
527    text.textContent = label;
528    
529    el.append(text);
530
531    // remove button
532    var remove_btn = document.createElement('div');
533    remove_btn.classList.add('remove');
534    el.append(remove_btn);
535    
536    remove_btn.addEventListener('click', ()=>{
537        _.remove_filter_indicator(el, type, key);
538    });
539
540    _.filter_indicators[key] = {
541        el: el,
542        text: text,
543        remove_btn: remove_btn
544    }
545
546    _.filter_indicators_con.append(el);
547}
548
549FF_Ajax_2.prototype.remove_filter_indicator = function(el, type, key){
550    var _ = this;
551    el.remove();
552
553    if( typeof _.filters[type] !== 'undefined' ) {
554        delete _.filters[type][key];
555    }
556
557    delete _.filter_indicators[key];
558
559    _.remove_filter_query(type, key);
560    _.apply_filters();
561}
562
563FF_Ajax_2.prototype.update_filter_indicator_item = function( type, key, value, label ){
564    var _ = this;
565
566    if( !value ) {
567        // empty value selected, remove
568        // update - this won't trigger anymore
569        _.filter_indicators[key].el.remove();
570
571        if( typeof _.filters[type] !== 'undefined' ) {
572            delete _.filters[type][key];
573        }
574
575        delete _.filter_indicators[key];
576
577        return;
578    }
579
580    if( !label ) label = value;
581
582    // change
583    _.filter_indicators[key].text.textContent = label;
584}
585
586FF_Ajax_2.prototype.load_more_init = function(){
587    var _ = this;
588
589    _.page = 1;
590    
591    _.load_more_loading = false;
592    _.load_more_con = _.container.querySelector('.load-more-con');
593    _.load_more_btn = _.load_more_con.querySelector('.load_more_btn');
594    _.have_more_posts = !_.load_more_con.classList.contains('hide');
595
596    _.load_more_btn.addEventListener('click', ()=>{
597        // console.log('load more click');
598        if( !_.have_more_posts ) return;
599        if( _.load_more_loading ) return;
600        _.load_more_loading = true;
601        _.page++;
602        _.load_more_btn.classList.add('loading');
603        _.query(res =>{
604            console.log('after load more', res);
605            _.load_more_loading = false;
606            _.load_more_btn.classList.remove('loading');
607        });
608    });
609
610}
611
612FF_Ajax_2.prototype.check_have_more_posts = function(res){
613    var _ = this;
614    _.have_more_posts = res.have_more_posts;
615    
616    if( _.have_more_posts ) {
617        _.load_more_con.classList.remove('hide');
618    } else {
619        _.load_more_con.classList.add('hide');
620    }
621}
622
623FF_Ajax_2.prototype.date_query_format = function(date_text){
624    var temp = date_text.split('/');
625
626    // Y-m-d
627    // return temp[2] +'-'+ temp[0] +'-'+ temp[1];
628
629    // Ymd
630    return temp[2] + temp[0] + temp[1];
631}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.