Challenge:
You have a JSON-API which gives realtime-data. The user should be able to search this data with a faceted search to set options for selecting items.
Click here for a simple Faceted Search.
In action:
see api.json-content-importer.com/pro-faceted-search-in-action/
Example-Data:
Step 1: Create a page with the search-results
Create a JCI-template with these settings:
Name:
facetedresults
URL:
https://api.json-content-importer.com/extra/json/travel.json
urlparam4twig (parameters for the search):
cres#vmax#vmin#ch#sort#page#stxt
Template-Text / twig-code:
<!-- sort: {{urlparam.sort}}<br> stxt : {{urlparam.stxt}}<br> price: {{urlparam.vmin}} - {{urlparam.vmax}}<br> --> {% set maxp = 999999999999999999 %} {% set minp = 0 %} {% if urlparam.vmin %}{% set minp =urlparam.vmin %}{% endif %} {% if urlparam.vmax %}{% set maxp =urlparam.vmax %}{% endif %} {% set nof = 0 %} {% set sort = 'desc' %}{% if urlparam.sort=="sortup" %}{% set sort = '' %}{% endif %} {% set stxt= '' %}{% if urlparam.stxt %}{% set stxt = urlparam.stxt %}{% endif %} <script type="text/javascript"> var outitems = {}; {% for i in Offers | sortbyjsonfield("Sellprice,"~sort~",num") %} {% set out = '' %} {% if (i.Sellprice<=maxp and i.Sellprice>=minp ) %} {% if (urlparam.ch=="") or (urlparam.ch matches '/'~ (i.Resortname | md5) ~'/') %} {% if (urlparam.stxt=="") or (i.Resortname matches '/'~(urlparam.stxt)~'/i') %} {% set nof = nof + 1 %} {% set out = out ~ '<div class="table-row"><div class="table-col">' %} {% set out = out ~ '<b>' ~ nof ~ ": " ~ i.Hotelname ~ '</b><br>' %} {% set out = out ~ 'Location: ' ~ i.Resortname ~ '<br>' %} {% set out = out ~ i.Sellprice ~ ' Euro<br>' %} {% set out = out ~ i.Areaname ~ ': ' ~ i.Outdepdate ~ ' - ' ~ i.Indepdate ~ '<br>' %} {% set out = out ~ 'Flight: ' ~ i.Depaptname~ ' to ' ~ i.Arraptname ~ ',<br>operated by ' ~ i.Flightsuppler %} {% set out = out ~ '<br><a href="/trip-details?refnum=' ~ i.Refnum ~ '">more</a>' %} {% set out = out ~ '</div></div>' %} outitems["ch{{nof}}"] = '{{out | url_encode }}'; {% endif %} {% endif %} {% endif %} {% endfor %} <\/script> <div class="divtable">{% if nof >0 %} <div class="table-row"><div class="table-col"> {% set itemsperpage = 5 %} {% set noofpages = ((nof /itemsperpage) | round(0, 'ceil') )%} {% if noofpages>1 %} {{nof }} Found, Pagination: <select class=psgeofpagination name=page> {% for p in (0.. (noofpages-1)) %}{% set lowend = (p*itemsperpage +1) %}{% set highend = ((p+1)*itemsperpage) %}{% if highend >nof %}{% set highend =nof %}{% endif %}<option name="pag" lowend="{{lowend}}" value="{{p}}"> {{lowend }} - {{highend}}</option>{% endfor %}</select></div></div> {% endif %} <div id="resultareaitems"></div> {% else %} <div class="table-row"><div class="table-col"> Nothing found, change selection please </div></div> {% endif %} </div> <script type="text/javascript"> doPag({{nof }}); $j('.psgeofpagination').change(function(){ doPag({{nof }}); }); function doPag(noall) { let z = $j('.psgeofpagination').children("option:selected").text(); if (z=="") { z= "1-"+noall; } let lowhigh = z.split("-"); let low = parseInt(lowhigh[0].trim(), 10); let high = parseInt(lowhigh[1].trim(), 10); let textout = ""; for (ui = low ; ui <= high; ui++) { textout += decodeURIComponent(outitems["ch"+ui]); } $j("#resultareaitems").html(textout); } <\/script>
Leave the other settings like cache, twig-parser etc. as they are (default settings).
Create a WordPress-Page with this Shortcode:
[jsoncontentimporterpro nameoftemplate="facetedresults"]
Preview of this page should give you something like this: https://api.json-content-importer.com/get-faceted-results/.
Name this page “get-faceted-results” and publish it. The URL then should be DOMAIN/get-faceted-results/
Step 2: Check jQuery-Libs
The faceted search uses the jQuery-JavaScript-Libraries. Depending on the used WordPress-Template those libraries are already available. If not you can load them via ther JCI-options, Tab “Extra”.
Check what your template is offering here (like a css-grid or JS-libs).
In case of need load
- jQuery: Basic jquery-Lib
- jQuery-UI, jQuery-UI CSS: Libs for using a slider etc.
- jQuery-UI Touch Punch: for using sliders on mobile devices
- jQuery mobile JS, jQuery mobile CSS: for using on mobile devices
Step 3: Create a page with the facet-search-form and the results
Create a JCI-template with these settings:
Name:
facetedform
URL:
https://api.json-content-importer.com/extra/json/travel.json
Template-Text / twig-code:
{% set loop = Offers %} {% set resortList = [] %} {% set anz = 0 %} {% set maxprice = -1 %} {% set minprice = -1 %} {% set stxt = '' %} {% for r in loop %} {% set resortList = resortList | merge( {(r.Resortname) : 1 }) %} {% if r.Sellprice > maxprice %}{% set maxprice = r.Sellprice %}{% endif %} {% if r.Sellprice < minprice or minprice <0 %}{% set minprice = r.Sellprice %}{% endif %} {% endfor %} <table border=1> <tr><td valign=top> <div class="large-4 columns"> <form class=retform> <h3 class="smtxt">Text-Search:</h3> <input type="text" name="stxt" value="" class="smtxt" placeholder="Resortname-Search: Insert Text for search here"> <h3 class=smtxt>Price-Sort:</h3> <input type="radio" name="sort" id="sortup" value="sortup"><label for="sortup"> <span class=smtxt>low to high</span></label> <br><input type="radio" name="sort" id="sortdown" value="sortdown"><label for="sortdown"> <span class=smtxt>high to low</span></label> <h3 class=smtxt>Price:</h3> <div id="selectslider" class="smtxt"></div> <input id="slidervalmin" type="text" /><input id="slidervalmax" type="text" /> <h3 class=smtxt>Location:</h3> {% set resortList = (resortList | sortbyarray("ksort")) %} {% for k,v in resortList %} <input type="checkbox" class=ret id="{{k|md5}}" value=""><span class=smtxt>{{k}}</span><br> {% endfor %} </form> </td><td valign=top> <div class="large-8 columns"> <div id="resultarea">select settings on the left side</div> </div> </td></tr></table> <script type="text/javascript"> var zrt ="/get-faceted-results/?show=oc"; var $j = jQuery.noConflict(); $j('input[type=radio][name=sort][value=sortup]').prop('checked', true); doaj(); $j('.retform').change(function(){ doaj(); }); $j('.retform').keyup(function(){ doaj(); }); function doaj() { let postpayload = {}; let chk = ""; $j('.ret:checked').each(function(){ chk = chk + $j(this).attr('id') + "-"; }); postpayload["ch"] = chk ; postpayload["stxt"] = $j('input[name=stxt]').val(); postpayload["vmin"] = $j("#slidervalmin").val(); postpayload["vmax"] = $j("#slidervalmax").val(); postpayload["sort"] = $j('input[name=sort]:checked').val(); postpayload["ds"] = $j("#datestart").val(); postpayload["de"] = $j("#dateend").val(); $j.ajax({ url: zrt, type: "POST", data: postpayload, dataType: "text", success: function(result){ $j("#resultarea").html(result);}, error: function(result){ var resulterror ="Request failed. Try again later, please"; $j("#resultarea").html(resulterror); } }); } $j( "#selectslider" ).slider({ range: true, min: {{minprice}}, max: {{maxprice}}, values: [ {{minprice }}, {{maxprice}}], step: 0.01, slide: function(event, ui) { $j("#slidervalmin").val(ui.values[0]); $j("#slidervalmax").val(ui.values[1]); doaj(); } }); $j("#slidervalmin").val($j("#selectslider").slider("values", 0)); $j("#slidervalmax").val($j("#selectslider").slider("values",1)); <\/script> <style type="text/css"> #secondary { display: none; } #primary { width: 100%; } .smtxt { font-size: 12px !important; } #slidervalmax, #slidervalmin{ background-color: #ddd; } .divtable { display: table; width: 100%; table-layout: fixed; border: 1px solid #666666; border-spacing: 5px; /* cellspacing:poor IE support for this */ } .table-row { display: table-row; width: auto; clear: both; } .table-col { float: left; /* fix for buggy browsers */ padding: 12px; display: table-column; } .divtableall { display: table; table-layout: auto; width: auto; font: 15px Arial, sans-serif; border-spacing: 5px; /* cellspacing:poor IE support for this */ } .tablerowall { display: table-row; clear: both; } .tablecolall { float: left; /* fix for buggy browsers */ padding: 15px; display: table-column; background-color: #eee; } .tablecolall25 { width: 25%; } .tablecolall75 { width: 75%; background-color: #ddd; } .row input[type=text] { width: 35%; padding: 5px; } .row h3 { margin-bottom: 6px; } @media only screen and (max-width: 768px){ .site-main .entry .entry-header { margin: calc(3 * 1rem) calc(5% + 60px) 1rem; } .site-main .entry .entry-content, .entry .entry-summary { padding: 0; } .site-main .row input[type=text] { display: inline-block; margin-top: 25px; } .site-main .ui-widget.ui-widget-content { margin-left: 13px; margin-top: 15px; } [type="checkbox"] { float: right !important; } .site-main .divtable { margin-top: 25px; } b,strong { font-weight: bolder; font-size: 34px !important; } } </style>
Leave the other settings like cache, twig-parser etc. as they are (default settings).
Create a WordPress-Page with this Shortcode:
[jsoncontentimporterpro nameoftemplate="facetedform"]
Preview of this page should give you something like this: https://api.json-content-importer.com/pro-faceted-search-in-action/.
Step 4: Create a page with the details of an item
Create a JCI-template with these settings:
Name:
faceteddetail
URL:
https://api.json-content-importer.com/extra/json/travel.json
urlparam4twig (parameters for the search)):
refnum
Template-Text / twig-code:
{% for i in Offers %} {% if urlparam.refnum==i.Refnum %} {{i |json_encode() }} {% endif %} {% endfor %}
Leave the other settings like cache, twig3 etc. as they are (default settings).
Saving this JCI-template gives you a number for this template. Use this on a page like that:
[jsoncontentimporterpro nameoftemplate="faceteddetail"]
Name this page “trip-details” and publish it. A click on “more” in the facet-result-list should take you to this page.
Well – that’s it. For other JSON you have to alter the twig-code to sum up the facet-options.