Script to display text and image from airtable

Hello everyone, I spent my weekend on a bug and it annoys me, I call on your writing skills :sweat_smile:

I’m looking to do something simple, in a list-details type page, display text and image content from the airtable content of the record.

Why ? Because I have a lot of data to display and I can’t settle for softr fields, so I found a UX with these small clickable panes. It’s going to work pretty well I think but I can’t display my content.

I found these examples: @dcoletta’s post and this post.

Here is a simple GIF showing the UX and the needs, that you can check under this link

CleanShot 2023-01-30 at 11.30.14

Thank you very much, I’ll buy you a beer when you go to France :beers:

Here is the code currently used in the custom code block


<html>
  <body>     
  <div class="tab">
    <button class="tablinks" onclick="printCrablyUrl()"><i class="fas fa-print"></i> Print menu</button>
    <button class="tablinks" onclick="openCity(event, 'QR')"><i class="fas fa-qrcode"></i> Flashcode menu</button>
    <button class="tablinks" onclick="openCity(event, 'Plan')" id="defaultOpen"><i class="fa-solid fa-layer-group"></i> Menu text</button>
    <button class="tablinks" onclick="openCity(event, 'Papier');displayA43()"><i class="fa-solid fa-file-lines"></i> Preview menu</button>
  </div>

  <div id="QR" class="tabcontent">
    <p> here I want to display <b>an image from an attachement</b> field named `QRcodemenu`into my airtable base. I tried different script but without success. The purpose is simply to display an image. </p>
</div>

  <div id="Plan" class="tabcontent">
  <p> here I want to display the text  from a <b>rich text field</b> named `themenutext`into my airtable base. I tried different script but without success, the purpose is only to fill my page with some text.  </p>
  </div>

  <div id="Papier" class="tabcontent">
    <iframe src="" id="iframeA4" width="100%" height="500px"  style="display: none"; allowfullscreen =""></iframe>
  </div>
  
  </body>
  
  <style>
    

  /* Style the tab */
  .tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
  }
  
  /* Style the buttons inside the tab */
  .tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 13px;
  }
  
  /* Change background color of buttons on hover */
  .tab button:hover {
    background-color: #ddd;
  }
  
  /* Create an active/current tablink class */
  .tab button.active {
    background-color: #ccc;
  }
  
  /* Style the tab content */
  .tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
  }
  </style>
  
  <script>
      // get the recordid
      var recordId = getUrlParam('recordId');
      function getUrlParam(name) {
              var url = new URL(window.location.href);
              let param;
              for (var key of url.searchParams.keys()) {
                  if (key.toLowerCase() === name.toLowerCase()) {
                      param = url.searchParams.get(name);
                      break;
                  }
              }
  
              if (!param && name.toLowerCase() === 'recordid') {
                  param = getRecordIdFromPath();
              }
              return param;
          }
      function getRecordIdFromPath() {
              let pathName = window.location.pathname;
              if (pathName.indexOf('/r/rec') !== -1) {
                  pathName = pathName.substr(pathName.indexOf('/r/rec') + 3);
                  if (pathName.indexOf("/") !== -1) {
                      pathName = pathName(0, pathName.indexOf('/'))
                  }
                  return pathName;
              }
              return undefined;
          }
          
  // display iframe with menu  
  function displayA43()
  {
      var string = window.records[recordId].record.fields['pdf'];
      var urlPDF = string.match(/\(([^)]+)\)/)[1];
      var iframeA4 = document.getElementById("iframeA4");
      document.getElementById('iframeA4').src = urlPDF + "#toolbar=0&view=FitH";
      iframeA4.style.display = "block";

  }
  
  // print the menu 
  function printCrablyUrl() {
          var string = window.records[recordId].record.fields['pdf'];
          var urlPDF = string.match(/\(([^)]+)\)/)[1];
          printJS(urlPDF);
  }
 
      
  // window switch
  function openCity(evt, cityName) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName("tabcontent");
    for (i = 0; i < tabcontent.length; i++) {
      tabcontent[i].style.display = "none";
    }
    tablinks = document.getElementsByClassName("tablinks");
    for (i = 0; i < tablinks.length; i++) {
      tablinks[i].className = tablinks[i].className.replace(" active", "");
    }
    document.getElementById(cityName).style.display = "block";
    evt.currentTarget.className += " active";
  }
  
  // Get the element with id="defaultOpen" and click on it
  document.getElementById("defaultOpen").click();

  </script>
  </html>
  

Hey @lea, let’s see what @artur thinks about this :slight_smile:

1 Like

And I’m a little afraid of the upcoming update concerning security, if we can no longer access certain fields that are not displayed. But I have no doubt, @artur must know the forks to come :slight_smile:

We most probably will end up giving you a dynamic custom code block where you could map fields to be available within the block to use. wdyt ?

1 Like

This sounds like a good idea

But despite everything, do you know how I could progress on my problem in the first post? Just a rough idea about the organization of the javascript code could help, I tried different solution without success :slight_smile:

An idea ? :slight_smile:

Hi @lea I’m not sure I get this right. Do you need a custom code block or a details block which shows a html/dynamic data from Airtable ?

the idea is to adapt my custom code block, I would simply like to succeed in “displaying airtable data” such as text fields for example. it’s a bit like what the studio already allows but it allows you to shape it differently. :slight_smile:

For now it’s hard to access Airtable data via custom code. I would suggest adding a block with the fields you need wait it to load, then hide and use window records to access the data from your custom code block

Like this example ? Here Matthieu is using blocks, we can do the same with fields from a details block ? :slight_smile:

Is it what you’re looking for as a result?
I hide/show specific elements (fields) of only one list details block

That’s the idea ! What is your code to achieve this UX ? Thanks @matthieu_chateau :slight_smile:

Here is the code.
I just updated it so that the content can be always centered (otherwise it’s ugly). Also, be sure to center align all the content of the list details in the softr studio.
Which make me think that I have to mention that I added the additional code part (var…) because when using Hide/Show, the content always go to the left (which is normal at the end… but ugly) even if centered in the Studio (I hope I’m understandable :sweat_smile:)

Here is the demo so you can understand by yourself where does “css-s1o41q” come from. Play with the inspector to find it: https://test-play.softr.app/hide-show-fields

<script>
   window.addEventListener('DOMContentLoaded', (event) => {
       document.getElementsByClassName('css-s1o41q')[0].style.display = "block";
       document.getElementsByClassName('css-s1o41q')[1].style.display = "none";
       document.getElementsByClassName('css-s1o41q')[2].style.display = "none";
       var parent = document.getElementsByClassName('css-s1o41q')[0].parentNode;
               parent.style.display = "flex"; 
               parent.style.justifyContent = "center";
               parent.style.alignItems = "center";
   });


   // This is being called when CTA block is rendered
   window.addEventListener('block-loaded-cta1', () => {
       console.log('CTA Block loaded');

       // function for button click handler
       const buttonClickHandler = (e) => {
           if (e.target.closest('#cta1 a[data-element="button"]:nth-child(1)')) {
               console.log('Click Button 1');
               document.getElementsByClassName('css-s1o41q')[0].style.display = "block";
               document.getElementsByClassName('css-s1o41q')[1].style.display = "none";
               document.getElementsByClassName('css-s1o41q')[2].style.display = "none";
               var parent = document.getElementsByClassName('css-s1o41q')[0].parentNode;
               parent.style.display = "flex"; 
               parent.style.justifyContent = "center";
               parent.style.alignItems = "center";
           }
           if (e.target.closest('#cta1 a[data-element="button"]:nth-child(2)')) {
               console.log('Click Button 2');
               document.getElementsByClassName('css-s1o41q')[1].style.display = "block";
               document.getElementsByClassName('css-s1o41q')[0].style.display = "none";
               document.getElementsByClassName('css-s1o41q')[2].style.display = "none";
               var parent = document.getElementsByClassName('css-s1o41q')[1].parentNode;
               parent.style.display = "flex"; 
               parent.style.justifyContent = "center";
               parent.style.alignItems = "center";
           }
           if (e.target.closest('#cta1 a[data-element="button"]:nth-child(3)')) {
               console.log('Click Button 3');
               document.getElementsByClassName('css-s1o41q')[2].style.display = "block";
               document.getElementsByClassName('css-s1o41q')[0].style.display = "none";
               document.getElementsByClassName('css-s1o41q')[1].style.display = "none";
               var parent = document.getElementsByClassName('css-s1o41q')[2].parentNode;
               parent.style.display = "flex"; 
               parent.style.justifyContent = "center";
               parent.style.alignItems = "center";
           }
       };
       
       //
       document.body.addEventListener('click', buttonClickHandler);
   });

</script>
1 Like

It sounds amazing

Hi, how can window records be accessed?