Google Books API - how to improve naff description

Eventually managed to tame Google Books API but would be grateful for suggestions to improve the naff descriptions which are rendered by selecting more.

Online demo

Searched books appear in a responsive block size and renders a brief description. The description can be Null, short (couple of lines) or verbose with umpteen lines that would either break out of the fixed block size or require an overflow-auto.

I am currently displaying about 420 characters and passing the complete description to a naff JavaScript alert("…"); and would be grateful for suggestions that I could search and make the layout not only responsive but also aesthetic.

[off-topic JavaScript question]
Embedded apostrophes passed to the JavaScript alert(…) failed to render any description and after numerous trial and errors managed to dynamically prefix the apostrophe with a backslash.

What is the the correct way to pass a lengthy string to a JavaScript function?
[/off-topic JavaScript question]

depends on the function.

If an apostrophe is going to choke it off, .replace("'","\\'") should work.

EDIT: Except javascript’s replace function isnt global. Derp Marc. Try that again… .replace(/'/g,"\\'")

I use server side PHP str_replace(…); and it is quite nippy. Just noticed I think I also use over-kill :slight_smile:

  $blurb = (string) $item['volumeInfo']['description'];
  $blurb = htmlspecialchars($blurb);
  $blurb = strip_tags($blurb);
  $blurb = str_replace("'", "\'", $blurb);
  $more  = substr($blurb, 0, 420); 

  $strlen = strlen($more);
  $btn  = <<< ________EOT
     <div class="tal p42"> 
       <br>
       $more 
       <div onclick="blurb('$idx', '$blurb')" class="tar fwb p42 hvr"> 
          ...more
        </div> 
      </div>  
      <div id='myDIV$idx' class="hhh HIDDEN-BUT-ESSENTIAL">$idx</div>
________EOT;

$btn  = strlen($more) ? $btn : '';

… careful there. PHP will consume that first \ as it processes the double quoted string. You’ve just told the string to replace an apostrophe with an apostrophe.

Without the leading left-hand slash the following JavaScript call failed - took me ages to pinpoint the problem! :slight_smile:

 <div onclick="blurb('$idx', '$blurb')" class="tar fwb p42 hvr"> 

Using the PHP str_replace(…) solved the alert failure. The single apostrophe was replaced with \’ satisfactorily.



Edit:

The following would have failed without using PHP str_replace(…)

Jack Reacher comes to the aid of Edward Lane, the head of an illegal soldiers-for-hire operation, who enlists Reacher’s assistance to find and stop a vicious kidnapper who has abducted Lane’s wife and child, but Reacher soon discovers that his new employer’s dirty secrets could get him killed.



Although the following leaves a lot to be desired but at least it is not failing to render :slight_smile:

"Featuring Jack Reacher, hero of the blockbuster movie starring Tom Cruise, as he comes to the UK. /b> /b>Jack Reacher is alone, the way he likes it. He watches a man cross a New York street and drive away in a Mercedes. The car contains $1 million of ransom money. Reacher’s job is to make sure it all turns out right - money paid, family safely returned. But Reacher is in the middle of a nasty little war

That’s… interesting. Normally PHP’s string scourer would chunk anything with an escape slash regardless of if it made sense. Anyway. From the looks of your output, something went wonky with strip_tags. You might want to strip the tags before htmlspecialcharing the string, because htmlspecialchars will chew on the <>'s.

Hi there John.

does this help with the naff bit…

<script>
function blurb( $idx, $blurb ) { 
  var x = document.getElementById( 'myDIV' + $idx );
  if ( x.textContent === $idx ) {
       x.textContent = $blurb;
       x.classList.remove( 'hhh' );
    } 
  else {
       x.innerHTML = $idx;
       x.classList.add( 'hhh' );
    }
 }
</script>

I don’t like your inline event handler handler, though. :eek:

Without it you might have a chance to change
…more” to “…less”. :winky:

coothead

I get the impression that it is GIGO :frowning:

I have removed strip_tags(…) and it works a little bit better.

I am curious to know of another solution which does not use JavaScript’s alert(…) function.

'enough for one day - I am off to read my book.

I like your solution, definitely a step in the right direction of eliminating the JavaScript alert(…)

I have updated the online demo. Is it possible to not repeat the brief description or to dab the remaining blurb on the end?

    if($results):
      foreach ($results as $key => $item) :
        $bgx  = $key % 2 ? ' bgc' : ' bgs';

        $info = $item['volumeInfo']['imageLinks'];
        $img  = $item['volumeInfo']['imageLinks']['thumbnail'];
        $img  = str_replace('http://', 'https://', $img);
        $img  = strlen($img) > 5 ? $img : 'https://supiet2.tk/assets/imgs/h1Logo.png';

        $get  = isset( $_GET['id']) ? $_GET['id'] : NULL;
        $idx  = $item['id'];

        $blurb = (string) $item['volumeInfo']['description'];
       # $blurb = strip_tags($blurb);
        $blurb = htmlspecialchars($blurb);
        $blurb = str_replace("'", "\'", $blurb);
        $more  = substr($blurb, 0, 360); 

        $strlen = strlen($more);
        $btn  = <<< ________EOT
          <div class="tal p42"> 
            <br>
            $more 
            <div onclick="blurb('$idx', '$blurb')" class="tar fwb p42 hvr"> 
              ...more
            </div> 
          </div>  
          <div id='myDIV$idx' class="hhh ESSENTIAL">$idx</div>
________EOT;
        $btn  = strlen($more) ? $btn : '';
        $info = <<< ____EOT
          <dd> <br><br> </dd>
          <dd class="clb w88 mga fg0 ofa $bgx ">
            <img class="fll" src="$img" alt="#"> 

            <div class="ooo"> 
              Author: &nbsp; 
                <b> 
                  {$item['volumeInfo']['authors'][0]} 
                  &nbsp; 
                </b>
            </div>

            <div class="ooo"> 
              Title: &nbsp; &nbsp;&nbsp; 
              <b> {$item['volumeInfo']['title']} </b>
            </div> 
            $btn

            <!--
              <i class="hhh clb tac"> &nbsp;STUFF Goes here </i>
              <b class="hhh ooo bd1"> &nbsp; </b>
            -->
          </dd>
____EOT;
        echo $info;
      endforeach;
    /* if($results): */ endif; 

So… the ‘more’ would be everything from 360 to the end… substring your blurb again, and pass that to your function instead of the full blurb.

1 Like

Great minds think alike - have just implemented the revision.

Removed $more and added $first and $last

    if($results):
      foreach ($results as $key => $item) :
        $bgx  = $key % 2 ? ' bgc' : ' bgs';

        $info = $item['volumeInfo']['imageLinks'];
        $img  = $item['volumeInfo']['imageLinks']['thumbnail'];
        $img  = str_replace('http://', 'https://', $img);
        $img  = strlen($img) > 5 ? $img : 'https://supiet2.tk/assets/imgs/h1Logo.png';

        $get  = isset( $_GET['id']) ? $_GET['id'] : NULL;
        $idx  = $item['id'];

        $blurb = (string) $item['volumeInfo']['description'];
       # $blurb = strip_tags($blurb);
        $blurb = htmlspecialchars($blurb);
        $blurb = str_replace("'", "\'", $blurb);
        $first = substr($blurb, 0, 360); 
        $last  = substr($blurb, 360); 

        $strlen = strlen($first);
        $btn  = <<< ________EOT
          <div class="tal p42"> 
            <br>
            $first 
            <div id='myDIV$idx' class="hhh ESSENTIAL">$idx</div>
            <div onclick="blurb('$idx', '$last')" class="tar fwb p42 hvr"> 
              ...toggle more/less
            </div> 
          </div>  
________EOT;
        $btn  = strlen($first) ? $btn : '';
        $info = <<< ____EOT
          <dd> <br><br> </dd>
          <dd class="clb w88 mga fg0 ofa $bgx ">
            <img class="fll" src="$img" alt="#"> 

            <div class="ooo"> 
              Author: &nbsp; 
                <b> 
                  {$item['volumeInfo']['authors'][0]} 
                  &nbsp; 
                </b>
            </div>

            <div class="ooo"> 
              Title: &nbsp; &nbsp;&nbsp; 
              <b> {$item['volumeInfo']['title']} </b>
            </div> 
            $btn

            <!--
              <i class="hhh clb tac"> &nbsp;STUFF Goes here </i>
              <b class="hhh ooo bd1"> &nbsp; </b>
            -->
          </dd>
____EOT;
        echo $info;
      endforeach;
    /* if($results): */ endif; 

No doubt it could be further optimised but that is definitely enough for today.

Many thanks @m_hutley and @coothead

Hi there John_Betong,

if you change this in your PHP…

<div onclick="blurb('$idx', '$last')" class="tar fwb p42 hvr"> 
...toggle more/less
</div>

to this…

<div onclick="blurb('$idx', '$last', event )" class="tar fwb p42 hvr">
 ... more
</div>

… and the script to this…

<script>
function blurb( $idx, $blurb, e ) {
  var x = document.getElementById( 'myDIV' + $idx );
  if ( x.textContent === $idx ) {
       x.textContent = $blurb;
       x.classList.remove( 'hhh' );
       e.target.textContent = '...less';
    } 
  else {
       x.textContent = $idx;
       x.classList.add( 'hhh' );
       e.target.textContent = '...more';
    }
 }
</script>

…the more and less will work. :winky:

coothead

1 Like

Many thanks - it works a treat :slight_smile:

The script has been modified to only show the more button when there is additional $last content to being shown…

…unfortunately it is a Kludge and not designed from the ground up

Is it possible to default to showing the $first and onclick(,) show $first and $last in the same <div> because the more button appears between the two split variables:

<?php
echo '<div class="tac">';
  echo '<h4 class="fsl bgd tal"> Found: ' .$cnt .' books </h4>';

  if($results): //================================================
    foreach ($results as $key => $item) :
      $bgx    = $key % 2 ? ' bgc' : ' bgs';

      $info   = $item['volumeInfo']['imageLinks'];
      $img    = $item['volumeInfo']['imageLinks']['thumbnail'];
      $img    = str_replace('http://', 'https://', $img);
      $img    = strlen($img) > 5 ? $img : 'https://supiet2.tk/assets/imgs/h1Logo.png';

      # $get  = isset( $_GET['id']) ? $_GET['id'] : NULL;
      $idx    = $item['id'];

      $blurb  =  (string) $item['volumeInfo']['description'];
     # $blurb = strip_tags($blurb);
      $blurb  = htmlspecialchars($blurb);
      $blurb  = str_replace("'", "\'", $blurb);
      $first  = substr($blurb, 0, 360) ;
      $last   = substr($blurb, 360) ; 

      $lenF   = strlen( (string) $first);
      $lenL   = strlen( (string) $last);

      $MORE   = ''; // NO MORE
      if($lenL) :
        $MORE = <<< ____EOT
           <div 
              class="tar fsl fwb p42 hvr $bgx"
              onclick="blurb('$idx', '$last', event )" 
            >
               &nbsp;&nbsp; ... more &nbsp;&nbsp; 
           </div>
____EOT;
      endif; // NOT MORE ==================

      $DEBUG = 'MAYBE NOT DISPLAYED BECAUSE OF LENGTH';
      $strlen = strlen($first);
      $btn  = <<< ________EOT
        <div class="tal p42"> 
          <!-- br -->
          $first 
          $MORE

          <div id='myDIV$idx' class="hhh fll mb2 ESSENTIAL">$idx</div>

        </div>  
________EOT;
      
      $btn  = strlen($first) ? $btn : '';


      // =================================================================
      ECHO $info = <<< ____EOT
        <dl class="$bgx bd1 tal" style="height:220px;">
          <dd class="clb w88 mga fg0">
            <img class="fll" src="$img" alt="#"> 

            <div class="ooo"> 
              Author: &nbsp; 
                <b> 
                  {$item['volumeInfo']['authors'][0]} 
                  &nbsp; 
                </b>
            </div>

            <div class="ooo"> 
              Title: &nbsp; &nbsp;&nbsp; 
              <b> {$item['volumeInfo']['title']} </b>
            </div> 
            <div class="DEBUG"> <br>  </div>
            <!-- $lenF  :  $lenL -->

            $btn

            <!--
              <i class="hhh clb tac"> &nbsp;STUFF Goes here </i>
              <b class="hhh ooo bd1"> &nbsp; </b>
            -->
          </dd>
          <dd> <br> </dd>
        </dl>
        <p> <br> </p>
____EOT;
      // =================================================================
    endforeach;
  endif; // if($results): 

echo '</div><!-- class="tac" -->';

Hi there John,

don’t forget to click the link at the bottom left of your page. :rofl:

Also note that your document is missing .<meta charset="utf-8"> :eek:

It also appears that some of the …more" links are getting cut off
mid word. Is that because of this…

I am currently displaying about 420 characters

coothead

1 Like

PHP for “Find the nearest word break”:

$fpos = 420-strrpos($first," ");
$lpos = strpos($last," ");
if($fpos > $lpos ) { //The closest space character is in the Last string.
  $first = $first.substr($last,0,$lpos); 
  $last = substr($last,$lpos); 
} else { //The closest space character is in the First string.
  $last = substr($first,420-$fpos).$last; 
  $first = substr($first,0,$fpos*-1); 
}

(Spitball code. There may need to be some +1’s or -1’s in there to ignore the space. Also some error checking to make sure there is a space in the last string.)

2 Likes

Many thanks for the script. I had already written my own to find the last space and it appears to be OK:

# ======================================================================
function getLastSpace
(
 string & $theLot, // NOT RETURNED AND BYREFERENCE IS FASTER 
 int    $iFirstLen = 555
)
:int // $iResult
{
  $first    = substr($theLot, 0, $iFirstLen);

  $iResult  = strrpos($first, ' ');
  if($iResult===FALSE) : // 
    $iResult = 0;
  endif;  

  return $iResult;
}//

Update the online version and it is behaving a lot better although I think the $first and $last descriptions don’t appear to be accurate.

Updated loop

``
echo ‘

’;
echo ’

Found: ’ .$cnt .’ books

';

if($results): //================================================
foreach ($results as $key => $item) :
$bgx = $key % 2 ? ’ bgc’ : ’ bge’;

  $info   = $item['volumeInfo']['imageLinks'];
  $img    = $item['volumeInfo']['imageLinks']['thumbnail'];
  $img    = str_replace('http://', 'https://', $img);
  $img    = strlen($img) > 5 ? $img : 'https://supiet2.tk/assets/imgs/h1Logo.png';

  $blurb  = (string) $item['volumeInfo']['description'];
 # $blurb = strip_tags($blurb);
 # $blurb  = htmlspecialchars($blurb);
  $blurb  = str_replace("'", "\'", $blurb);

  if(0):
    $iLast  = getLastSpace($blurb);
  else:  
    $tmp    = substr($blurb, 0, 555);
    $iLast  = strrpos($tmp, ' ');
    if($iLast===FALSE) : // 
      $iLast = 0;
    endif;  
  endif;

  $first  = substr($blurb, 0, $iLast) ;
  $last   = substr($blurb, $iLast) ; 

  $idx    = $item['id'];
  $MORE   = ''; // NO MORE
  if( strlen( (string) $last) ) :
    $MORE = <<< ____EOT
       <div 
          class="tar tar fsl fwb p42 $bgx"
          onclick="blurb('$idx', '$last', event )" 
        >
          ...more
       </div>

____EOT;
endif; // NOT MORE ==================

  $DEBUG = 'MAYBE NOT BE DISPLAYED BECAUSE OF LENGTH';
  $strlen = strlen($first);
  $btn  = <<< ________EOT
    <div id='myDIV$idx' class="hhh fll XXXmb2 ESSENTIAL">
      $idx
    </div>

    <div class="XXXtal"> 
      $MORE
    </div>  

________EOT;

  $btn  = strlen($first) ? $btn : '';


  // =================================================================
  ECHO $info = <<< ____EOT
    <dl class="$bgx bd1 tal">
      <dt> &nbsp; </dt> <!-- kludge -->
      <dd class="clb w88 mga fg0">
        <img class="fll" src="$img" alt="#"> 

        <div class="ooo"> 
          Author: &nbsp; 
            <b> 
              {$item['volumeInfo']['authors'][0]} 
              &nbsp; 
            </b>
        </div>

        <div class="ooo"> 
          Title: &nbsp; &nbsp;&nbsp; 
          <b> {$item['volumeInfo']['title']} </b>
        </div> 
        <div class="DEBUG"> <br>  </div> <!-- lenF  :  lenL : iLast -->
        $first
        $btn

        <!--
          <i class="hhh clb tac"> &nbsp;STUFF Goes here </i>
          <b class="hhh ooo bd1"> &nbsp; </b>
        -->
      </dd>
      <dd> <br> </dd>
    </dl>
    <p> <br> </p>

____EOT;
// =================================================================
endforeach;
endif; // if($results):

echo ‘

’;

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.